add iSCSI protocol

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@4423 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
eric_tian 2007-12-24 02:20:21 +00:00
parent e3b1115ed8
commit 6a690e23d7
30 changed files with 10921 additions and 0 deletions

View File

@ -24,6 +24,8 @@ Abstract:
#define _NET_LIB_H_
#include <PiDxe.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/ComponentName.h>
#include <Protocol/DriverConfiguration.h>
@ -214,6 +216,8 @@ extern EFI_IPv4_ADDRESS mZeroIp4Addr;
#define NET_IS_DIGIT(Ch) (('0' <= (Ch)) && ((Ch) <= '9'))
#define NET_ROUNDUP(size, unit) (((size) + (unit) - 1) & (~((unit) - 1)))
#define NET_IS_LOWER_CASE_CHAR(Ch) (('a' <= (Ch)) && ((Ch) <= 'z'))
#define NET_IS_UPPER_CASE_CHAR(Ch) (('A' <= (Ch)) && ((Ch) <= 'Z'))
//
// Wrap functions to ease the impact of EFI library changes.

View File

@ -35,6 +35,7 @@
PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
FrameworkIfrSupportLib|IntelFrameworkPkg/Library/FrameworkIfrSupportLib/IfrSupportLib.inf
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
@ -257,6 +258,8 @@
MdeModulePkg/Library/PeiS3LibNull/PeiS3LibNull.inf
MdeModulePkg/Library/PeiRecoveryLibNull/PeiRecoveryLibNull.inf
MdeModulePkg/Universal/iScsi/IScsi.inf
MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf

View File

@ -0,0 +1,146 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
ComponentName.c
Abstract:
ComponentName protocol for iSCSI.
--*/
#include "IScsiImpl.h"
//
// EFI Component Name Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gIScsiComponentName = {
IScsiComponentNameGetDriverName,
IScsiComponentNameGetControllerName,
"eng"
};
//
// EFI Component Name 2 Protocol
//
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gIScsiComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) IScsiComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) IScsiComponentNameGetControllerName,
"en"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mIScsiDriverNameTable[] = {
{"eng;en", L"iSCSI Driver"},
{NULL, NULL}
};
EFI_STATUS
EFIAPI
IScsiComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that that the caller
is requesting, and it must match one of the languages specified
in SupportedLanguages. The number of languages supported by a
driver is up to the driver writer.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
mIScsiDriverNameTable,
DriverName,
(BOOLEAN)(This == &gIScsiComponentName)
);
}
EFI_STATUS
EFIAPI
IScsiComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that that the caller is requesting, and it must match one
of the languages specified in SupportedLanguages. The
number of languages supported by a driver is up to the
driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language
specified by Language from the point of view of the
driver specified by This.
Returns:
EFI_SUCCESS - The Unicode string for the user readable name in the
language specified by Language for the driver
specified by This was returned in DriverName.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,96 @@
#/** @file
# Component description file for iSCSI module.
#
# Copyright (c) 2006 - 2007, Intel Corporation
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = iSCSI
FILE_GUID = 4579B72D-7EC4-4dd4-8486-083C86B182A7
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = IScsiDriverEntryPoint
UNLOAD_IMAGE = EfiIScsiUnload
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
# DRIVER_BINDING = gIScsiDriverBinding
# COMPONENT_NAME = gIScsiComponentName
#
[Sources.common]
IScsiTcp4Io.h
IScsiProto.h
IScsiMisc.h
IScsiIbft.h
IScsiExtScsiPassThru.h
IScsiDriver.h
IScsiDhcp.h
IScsiCommon.h
IScsiCHAP.h
IScsiTcp4Io.c
IScsiProto.c
IScsiMisc.c
IScsiInitiatorName.c
IScsiIbft.c
IScsiExtScsiPassThru.c
IScsiDriver.c
IScsiDhcp.c
IScsiCHAP.c
ComponentName.c
Md5.c
IScsiConfigDxeStrings.uni
IScsiConfigDxe.vfr
IScsiConfig.c
IScsiConfig.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
IntelFrameworkPkg/IntelFrameworkPkg.dec
IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec
[LibraryClasses]
UefiDriverEntryPoint
UefiLib
BaseLib
MemoryAllocationLib
BaseMemoryLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
DevicePathLib
DebugLib
PrintLib
FrameworkHiiLib
FrameworkIfrSupportLib
NetLib
[Protocols]
gEfiIScsiInitiatorNameProtocolGuid
gEfiBlockIoProtocolGuid
gEfiTcp4ProtocolGuid
gEfiExtScsiPassThruProtocolGuid
gEfiDevicePathProtocolGuid
gEfiTcp4ServiceBindingProtocolGuid
gEfiFormCallbackProtocolGuid
gEfiFormBrowserProtocolGuid
gEfiPciIoProtocolGuid
gEfiAcpiSupportProtocolGuid
gEfiDhcp4ProtocolGuid
gEfiDhcp4ServiceBindingProtocolGuid

View File

@ -0,0 +1,429 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiCHAP.c
Abstract:
--*/
#include "IScsiImpl.h"
#include "Md5.h"
EFI_GUID mIScsiCHAPAuthInfoGuid = ISCSI_CHAP_AUTH_INFO_GUID;
EFI_STATUS
IScsiCHAPCalculateResponse (
IN UINT32 ChapIdentifier,
IN CHAR8 *ChapSecret,
IN UINT32 SecretLength,
IN UINT8 *ChapChallenge,
IN UINT32 ChallengeLength,
OUT UINT8 *ChapResponse
)
{
MD5_CTX Md5Ctx;
CHAR8 IdByte[1];
EFI_STATUS Status;
Status = MD5Init (&Md5Ctx);
//
// Hash Identifier - Only calculate 1 byte data (RFC1994)
//
IdByte[0] = (CHAR8) ChapIdentifier;
MD5Update (&Md5Ctx, IdByte, 1);
//
// Hash Secret
//
if (SecretLength < ISCSI_CHAP_SECRET_MIN_LEN - 1) {
return EFI_PROTOCOL_ERROR;
}
MD5Update (&Md5Ctx, ChapSecret, SecretLength);
//
// Hash Challenge received from Target
//
MD5Update (&Md5Ctx, ChapChallenge, ChallengeLength);
Status = MD5Final (&Md5Ctx, ChapResponse);
return Status;
}
EFI_STATUS
IScsiCHAPAuthTarget (
IN ISCSI_CHAP_AUTH_DATA *AuthData,
IN UINT8 *TargetResponse
)
{
EFI_STATUS Status;
UINT32 SecretSize;
UINT8 VerifyRsp[ISCSI_CHAP_RSP_LEN];
Status = EFI_SUCCESS;
SecretSize = (UINT32) AsciiStrLen (AuthData->AuthConfig.ReverseCHAPSecret);
Status = IScsiCHAPCalculateResponse (
AuthData->OutIdentifier,
AuthData->AuthConfig.ReverseCHAPSecret,
SecretSize,
AuthData->OutChallenge,
AuthData->OutChallengeLength,
VerifyRsp
);
if (NetCompareMem (VerifyRsp, TargetResponse, ISCSI_CHAP_RSP_LEN)) {
Status = EFI_SECURITY_VIOLATION;
}
return Status;
}
EFI_STATUS
IScsiCHAPOnRspReceived (
IN ISCSI_CONNECTION *Conn,
IN BOOLEAN Transit
)
/*++
Routine Description:
This function checks the received iSCSI Login Response during the security
negotiation stage.
Arguments:
Conn - The iSCSI connection.
Transit - The transit flag of the latest iSCSI Login Response.
Returns:
EFI_SUCCESS - The Login Response passed the CHAP validation.
EFI_OUT_OF_RESOURCES - Failed to allocate memory.
EFI_PROTOCOL_ERROR - Some kind of protocol error happend.
--*/
{
EFI_STATUS Status;
ISCSI_SESSION *Session;
ISCSI_SESSION_CONFIG_DATA *ConfigData;
ISCSI_CHAP_AUTH_DATA *AuthData;
CHAR8 *Value;
UINT8 *Data;
UINT32 Len;
NET_LIST_ENTRY *KeyValueList;
UINTN Algorithm;
CHAR8 *Identifier;
CHAR8 *Challenge;
CHAR8 *Name;
CHAR8 *Response;
UINT8 TargetRsp[ISCSI_CHAP_RSP_LEN];
UINT32 RspLen;
ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
ASSERT (Conn->RspQue.BufNum != 0);
Session = Conn->Session;
ConfigData = &Session->ConfigData;
AuthData = &Session->AuthData;
Len = Conn->RspQue.BufSize;
Data = NetAllocatePool (Len);
if (Data == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Copy the data in case the data spans over multiple PDUs.
//
NetbufQueCopy (&Conn->RspQue, 0, Len, Data);
//
// Build the key-value list from the data segment of the Login Response.
//
KeyValueList = IScsiBuildKeyValueList (Data, Len);
if (KeyValueList == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
Status = EFI_PROTOCOL_ERROR;
switch (Conn->CHAPStep) {
case ISCSI_CHAP_INITIAL:
//
// The first Login Response.
//
Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG);
if (Value == NULL) {
goto ON_EXIT;
}
Session->TargetPortalGroupTag = (UINT16) AsciiStrDecimalToUintn (Value);
Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_AUTH_METHOD);
if (Value == NULL) {
goto ON_EXIT;
}
//
// Initiator mandates CHAP authentication but target replies without "CHAP" or
// initiator suggets "None" but target replies with some kind of auth method.
//
if (AsciiStrCmp (Value, ISCSI_AUTH_METHOD_CHAP) == 0) {
if (AuthData->AuthConfig.CHAPType == ISCSI_CHAP_NONE) {
goto ON_EXIT;
}
} else {
if (AuthData->AuthConfig.CHAPType != ISCSI_CHAP_NONE) {
goto ON_EXIT;
}
}
//
// Transit to CHAP step one.
//
Conn->CHAPStep = ISCSI_CHAP_STEP_ONE;
Status = EFI_SUCCESS;
break;
case ISCSI_CHAP_STEP_TWO:
//
// The Target replies with CHAP_A=<A> CHAP_I=<I> CHAP_C=<C>
//
Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_ALGORITHM);
if (Value == NULL) {
goto ON_EXIT;
}
Algorithm = AsciiStrDecimalToUintn (Value);
if (Algorithm != ISCSI_CHAP_ALGORITHM_MD5) {
//
// Unsupported algorithm is chosen by target.
//
goto ON_EXIT;
}
Identifier = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_IDENTIFIER);
if (Identifier == NULL) {
goto ON_EXIT;
}
Challenge = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_CHALLENGE);
if (Challenge == NULL) {
goto ON_EXIT;
}
//
// Process the CHAP identifier and CHAP Challenge from Target
// Calculate Response value
//
AuthData->InIdentifier = (UINT32) AsciiStrDecimalToUintn (Identifier);
AuthData->InChallengeLength = ISCSI_CHAP_AUTH_MAX_LEN;
IScsiHexToBin ((UINT8 *) AuthData->InChallenge, &AuthData->InChallengeLength, Challenge);
Status = IScsiCHAPCalculateResponse (
AuthData->InIdentifier,
AuthData->AuthConfig.CHAPSecret,
(UINT32) AsciiStrLen (AuthData->AuthConfig.CHAPSecret),
AuthData->InChallenge,
AuthData->InChallengeLength,
AuthData->CHAPResponse
);
//
// Transit to next step.
//
Conn->CHAPStep = ISCSI_CHAP_STEP_THREE;
break;
case ISCSI_CHAP_STEP_THREE:
//
// one way CHAP authentication and the target would like to
// authenticate us.
//
Status = EFI_SUCCESS;
break;
case ISCSI_CHAP_STEP_FOUR:
ASSERT (AuthData->AuthConfig.CHAPType == ISCSI_CHAP_MUTUAL);
//
// The forth step, CHAP_N=<N> CHAP_R=<R> is received from Target.
//
Name = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_NAME);
if (Name == NULL) {
goto ON_EXIT;
}
Response = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_CHAP_RESPONSE);
if (Response == NULL) {
goto ON_EXIT;
}
RspLen = ISCSI_CHAP_RSP_LEN;
IScsiHexToBin (TargetRsp, &RspLen, Response);
//
// Check the CHAP Name and Response replied by Target.
//
Status = IScsiCHAPAuthTarget (AuthData, TargetRsp);
break;
default:
break;
}
ON_EXIT:
IScsiFreeKeyValueList (KeyValueList);
NetFreePool (Data);
return Status;
}
EFI_STATUS
IScsiCHAPToSendReq (
IN ISCSI_CONNECTION *Conn,
IN NET_BUF *Pdu
)
/*++
Routine Description:
This function fills the CHAP authentication information into the login PDU
during the security negotiation stage in the iSCSI connection login.
Arguments:
Conn - The iSCSI connection.
Pdu - The PDU to send out.
Returns:
EFI_SUCCESS - All check passed and the phase-related CHAP authentication
info is filled into the iSCSI PDU.
EFI_OUT_OF_RESOURCES - Failed to allocate memory.
EFI_PROTOCOL_ERROR - Some kind of protocol error happend.
--*/
{
EFI_STATUS Status;
ISCSI_SESSION *Session;
ISCSI_LOGIN_REQUEST *LoginReq;
ISCSI_SESSION_CONFIG_DATA *ConfigData;
ISCSI_CHAP_AUTH_DATA *AuthData;
CHAR8 *Value;
CHAR8 ValueStr[256];
CHAR8 *Response;
UINT32 RspLen;
CHAR8 *Challenge;
UINT32 ChallengeLen;
ASSERT (Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION);
Session = Conn->Session;
ConfigData = &Session->ConfigData;
AuthData = &Session->AuthData;
LoginReq = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, 0);
Status = EFI_SUCCESS;
RspLen = 2 * ISCSI_CHAP_RSP_LEN + 3;
Response = NetAllocatePool (RspLen);
if (Response == NULL) {
return EFI_OUT_OF_RESOURCES;
}
ChallengeLen = 2 * ISCSI_CHAP_RSP_LEN + 3;
Challenge = NetAllocatePool (ChallengeLen);
if (Challenge == NULL) {
return EFI_OUT_OF_RESOURCES;
}
switch (Conn->CHAPStep) {
case ISCSI_CHAP_INITIAL:
//
// It's the initial Login Request. Fill in the key=value pairs mandatory
// for the initial Login Request.
//
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_INITIATOR_NAME, Session->InitiatorName);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_SESSION_TYPE, "Normal");
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_TARGET_NAME, Session->ConfigData.NvData.TargetName);
if (AuthData->AuthConfig.CHAPType == ISCSI_CHAP_NONE) {
Value = ISCSI_KEY_VALUE_NONE;
ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
} else {
Value = ISCSI_AUTH_METHOD_CHAP;
}
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_AUTH_METHOD, Value);
break;
case ISCSI_CHAP_STEP_ONE:
//
// First step, send the Login Request with CHAP_A=<A1,A2...> key-value pair.
//
AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", ISCSI_CHAP_ALGORITHM_MD5);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_ALGORITHM, ValueStr);
Conn->CHAPStep = ISCSI_CHAP_STEP_TWO;
break;
case ISCSI_CHAP_STEP_THREE:
//
// Third step, send the Login Request with CHAP_N=<N> CHAP_R=<R> or
// CHAP_N=<N> CHAP_R=<R> CHAP_I=<I> CHAP_C=<C> if target ahtentication is
// required too.
//
// CHAP_N=<N>
//
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_NAME, (UINT8 *) &AuthData->AuthConfig.CHAPName);
//
// CHAP_R=<R>
//
IScsiBinToHex ((UINT8 *) AuthData->CHAPResponse, ISCSI_CHAP_RSP_LEN, Response, &RspLen);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_RESPONSE, Response);
if (AuthData->AuthConfig.CHAPType == ISCSI_CHAP_MUTUAL) {
//
// CHAP_I=<I>
//
IScsiGenRandom ((UINT8 *) &AuthData->OutIdentifier, 1);
AsciiSPrint (ValueStr, sizeof (ValueStr), "%d", AuthData->OutIdentifier);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_IDENTIFIER, ValueStr);
//
// CHAP_C=<C>
//
IScsiGenRandom ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN);
AuthData->OutChallengeLength = ISCSI_CHAP_RSP_LEN;
IScsiBinToHex ((UINT8 *) AuthData->OutChallenge, ISCSI_CHAP_RSP_LEN, Challenge, &ChallengeLen);
IScsiAddKeyValuePair (Pdu, ISCSI_KEY_CHAP_CHALLENGE, Challenge);
Conn->CHAPStep = ISCSI_CHAP_STEP_FOUR;
}
//
// set the stage transition flag.
//
ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
break;
default:
Status = EFI_PROTOCOL_ERROR;
break;
}
NetFreePool (Response);
NetFreePool (Challenge);
return Status;
}

View File

@ -0,0 +1,95 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiCHAP.h
Abstract:
--*/
#ifndef _ISCSI_CHAP_H_
#define _ISCSI_CHAP_H_
#define ISCSI_CHAP_AUTH_INFO_GUID \
{ \
0x786ec0ac, 0x65ae, 0x4d1b, 0xb1, 0x37, 0xd, 0x11, 0xa, 0x48, 0x37, 0x97 \
}
extern EFI_GUID mIScsiCHAPAuthInfoGuid;
#define ISCSI_AUTH_METHOD_CHAP "CHAP"
#define ISCSI_KEY_CHAP_ALGORITHM "CHAP_A"
#define ISCSI_KEY_CHAP_IDENTIFIER "CHAP_I"
#define ISCSI_KEY_CHAP_CHALLENGE "CHAP_C"
#define ISCSI_KEY_CHAP_NAME "CHAP_N"
#define ISCSI_KEY_CHAP_RESPONSE "CHAP_R"
#define ISCSI_CHAP_ALGORITHM_MD5 5
#define ISCSI_CHAP_AUTH_MAX_LEN 1024
#define ISCSI_CHAP_RSP_LEN 16 // == MD5_HASHSIZE
typedef enum {
ISCSI_CHAP_INITIAL,
ISCSI_CHAP_STEP_ONE,
ISCSI_CHAP_STEP_TWO,
ISCSI_CHAP_STEP_THREE,
ISCSI_CHAP_STEP_FOUR
} ISCSI_CHAP_STEP;
#pragma pack(1)
typedef struct _ISCSI_CHAP_AUTH_CONFIG_NVDATA {
UINT8 CHAPType;
CHAR8 CHAPName[ISCSI_CHAP_NAME_MAX_LEN];
CHAR8 CHAPSecret[ISCSI_CHAP_SECRET_MAX_LEN];
CHAR8 ReverseCHAPName[ISCSI_CHAP_NAME_MAX_LEN];
CHAR8 ReverseCHAPSecret[ISCSI_CHAP_SECRET_MAX_LEN];
} ISCSI_CHAP_AUTH_CONFIG_NVDATA;
#pragma pack()
//
// ISCSI CHAP Authentication Data
//
typedef struct _ISCSI_CHAP_AUTH_DATA {
ISCSI_CHAP_AUTH_CONFIG_NVDATA AuthConfig;
UINT32 InIdentifier;
UINT8 InChallenge[ISCSI_CHAP_AUTH_MAX_LEN];
UINT32 InChallengeLength;
//
// Calculated CHAP Response (CHAP_R) value
//
UINT8 CHAPResponse[ISCSI_CHAP_RSP_LEN];
//
// Auth-data to be sent out for mutual authentication
//
UINT32 OutIdentifier;
UINT8 OutChallenge[ISCSI_CHAP_AUTH_MAX_LEN];
UINT32 OutChallengeLength;
} ISCSI_CHAP_AUTH_DATA;
EFI_STATUS
IScsiCHAPOnRspReceived (
IN ISCSI_CONNECTION *Conn,
IN BOOLEAN Transit
);
EFI_STATUS
IScsiCHAPToSendReq (
IN ISCSI_CONNECTION *Conn,
IN NET_BUF *Pdu
);
#endif

View File

@ -0,0 +1,28 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiCommon.h
Abstract:
--*/
#ifndef _ISCSI_COMMON_H_
#define _ISCSI_COMMON_H_
typedef struct _ISCSI_SESSION ISCSI_SESSION;
typedef struct _ISCSI_CONNECTION ISCSI_CONNECTION;
typedef struct _ISCSI_DRIVER_DATA ISCSI_DRIVER_DATA;
typedef struct _ISCSI_SESSION_CONFIG_DATA ISCSI_SESSION_CONFIG_DATA;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,111 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiConfig.h
Abstract:
--*/
#ifndef _ISCSI_CONFIG_H_
#define _ISCSI_CONFIG_H_
//#include "Tiano.h"
//#include "EfiDriverLib.h"
//#include "Base.h"
#include <Library/FrameworkHiiLib.h>
#include <Protocol/FrameworkFormBrowser.h>
#include <Protocol/FrameworkFormCallback.h>
#include <Library/FrameworkIfrSupportLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
//#include "EfiPrintLib.h"
//#include EFI_PROTOCOL_DEFINITION (Hii)
//#include EFI_PROTOCOL_DEFINITION (FormBrowser)
//#include EFI_PROTOCOL_DEFINITION (FormCallback)
#include <Library/NetLib.h>
#include "IScsiConfigNVDataStruc.h"
extern UINT8 IScsiConfigDxeBin[];
extern UINT8 iSCSIStrings[];
#define ISCSI_INITATOR_NAME_VAR_NAME L"I_NAME"
#define ISCSI_CONFIG_VAR_ATTR (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE)
#define ISCSI_FORM_CALLBACK_INFO_SIGNATURE EFI_SIGNATURE_32 ('I', 'f', 'c', 'i')
#define ISCSI_FORM_CALLBACK_INFO_FROM_FORM_CALLBACK(Callback) \
CR ( \
Callback, \
ISCSI_FORM_CALLBACK_INFO, \
FormCallback, \
ISCSI_FORM_CALLBACK_INFO_SIGNATURE \
)
#pragma pack(1)
typedef struct _ISCSI_MAC_INFO {
EFI_MAC_ADDRESS Mac;
UINT8 Len;
} ISCSI_MAC_INFO;
typedef struct _ISCSI_DEVICE_LIST {
UINT8 NumDevice;
ISCSI_MAC_INFO MacInfo[1];
} ISCSI_DEVICE_LIST;
#pragma pack()
typedef struct _ISCSI_CONFIG_FORM_ENTRY {
NET_LIST_ENTRY Link;
EFI_HANDLE Controller;
CHAR16 MacString[95];
STRING_REF PortTitleToken;
STRING_REF PortTitleHelpToken;
ISCSI_SESSION_CONFIG_NVDATA SessionConfigData;
ISCSI_CHAP_AUTH_CONFIG_NVDATA AuthConfigData;
} ISCSI_CONFIG_FORM_ENTRY;
typedef struct _ISCSI_FORM_CALLBACK_INFO {
UINTN Signature;
EFI_HANDLE CallbackHandle;
EFI_FORM_CALLBACK_PROTOCOL FormCallback;
UINT16 *KeyList;
VOID *FormBuffer;
EFI_HII_HANDLE RegisteredHandle;
EFI_HII_PROTOCOL *Hii;
ISCSI_CONFIG_FORM_ENTRY *Current;
} ISCSI_FORM_CALLBACK_INFO;
EFI_STATUS
IScsiConfigUpdateForm (
IN EFI_HANDLE DriverBindingHandle,
IN EFI_HANDLE Controller,
IN BOOLEAN AddForm
);
EFI_STATUS
IScsiConfigFormInit (
IN EFI_HANDLE DriverBindingHandle
);
EFI_STATUS
IScsiConfigFormUnload (
IN EFI_HANDLE DriverBindingHandle
);
#endif

View File

@ -0,0 +1,212 @@
// *++
//
//Copyright (c) 2007 Intel Corporation. All rights reserved
//This software and associated documentation (if any) is furnished
//under a license and may only be used or copied in accordance
//with the terms of the license. Except as permitted by such
//license, no part of this software or documentation may be
//reproduced, stored in a retrieval system, or transmitted in any
//form or by any means without the express written consent of
//Intel Corporation.
//
// Module Name:
//
// IScsiConfigVfr.vfr
//
// Abstract:
//
// Revision History:
//
// --*/
#include "IScsiConfigNVDataStruc.h"
#define EFI_NETWORK_DEVICE_CLASS 0x04
formset
guid = ISCSI_CONFIG_GUID,
title = STRING_TOKEN(STR_ISCSI_CONFIG_FORM_TITLE),
help = STRING_TOKEN(STR_ISCSI_CONFIG_FORM_HELP),
class = EFI_NETWORK_DEVICE_CLASS,
subclass = 0x03,
form formid = FORMID_MAIN_FORM,
title = STRING_TOKEN(STR_ISCSI_MAIN_FORM_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code
string varid = ISCSI_CONFIG_IFR_NVDATA.InitiatorName,
prompt = STRING_TOKEN(STR_ISCSI_CONFIG_INIT_NAME),
help = STRING_TOKEN(STR_ISCSI_CONFIG_INIT_NAME_HELP),
flags = INTERACTIVE,
key = KEY_INITIATOR_NAME,
minsize = 8,
maxsize = ISCSI_NAME_IFR_MAX_SIZE,
endstring;
label DEVICE_ENTRY_LABEL;
endform;
form formid = FORMID_DEVICE_FORM,
title = STRING_TOKEN(STR_ISCSI_DEVICE_FORM_TITLE);
checkbox varid = ISCSI_CONFIG_IFR_NVDATA.Enabled,
prompt = STRING_TOKEN(STR_ISCSI_DEVICE_ENABLE),
help = STRING_TOKEN(STR_NULL),
flags = 0,
endcheckbox;
checkbox varid = ISCSI_CONFIG_IFR_NVDATA.InitiatorInfoFromDhcp,
prompt = STRING_TOKEN(STR_ISCSI_ENABLE_DHCP),
help = STRING_TOKEN(STR_ISCSI_ENABLE_DHCP),
flags = INTERACTIVE,
key = KEY_DHCP_ENABLE,
endcheckbox;
suppressif ideqval ISCSI_CONFIG_IFR_NVDATA.InitiatorInfoFromDhcp == 0x01;
string varid = ISCSI_CONFIG_IFR_NVDATA.LocalIp,
prompt = STRING_TOKEN(STR_ISCSI_LOCAL_IP_ADDRESS),
help = STRING_TOKEN(STR_ISCSI_IP_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_LOCAL_IP,
minsize = IP_MIN_SIZE,
maxsize = IP_MAX_SIZE,
endstring;
string varid = ISCSI_CONFIG_IFR_NVDATA.SubnetMask,
prompt = STRING_TOKEN(STR_ISCSI_LOCAL_MASK),
help = STRING_TOKEN(STR_ISCSI_IP_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_SUBNET_MASK,
minsize = IP_MIN_SIZE,
maxsize = IP_MAX_SIZE,
endstring;
string varid = ISCSI_CONFIG_IFR_NVDATA.Gateway,
prompt = STRING_TOKEN(STR_ISCSI_LOCAL_GATEWAY),
help = STRING_TOKEN(STR_ISCSI_IP_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_GATE_WAY,
minsize = IP_MIN_SIZE,
maxsize = IP_MAX_SIZE,
endstring;
endif;
subtitle text = STRING_TOKEN(STR_NULL);
suppressif ideqval ISCSI_CONFIG_IFR_NVDATA.InitiatorInfoFromDhcp == 0x00;
checkbox varid = ISCSI_CONFIG_IFR_NVDATA.TargetInfoFromDhcp,
prompt = STRING_TOKEN(STR_ISCSI_ENABLE_DHCP_ON_TARGET),
help = STRING_TOKEN(STR_ISCSI_ENABLE_DHCP_ON_TARGET),
flags = 0,
endcheckbox;
endif;
suppressif ideqval ISCSI_CONFIG_IFR_NVDATA.TargetInfoFromDhcp == 0x01;
string varid = ISCSI_CONFIG_IFR_NVDATA.TargetName,
prompt = STRING_TOKEN(STR_ISCSI_TARGET_NAME),
help = STRING_TOKEN(STR_ISCSI_TARGET_NAME),
flags = INTERACTIVE,
key = KEY_TARGET_NAME,
minsize = 8,
maxsize = ISCSI_NAME_IFR_MAX_SIZE,
endstring;
string varid = ISCSI_CONFIG_IFR_NVDATA.TargetIp,
prompt = STRING_TOKEN(STR_ISCSI_TARGET_IP_ADDRESS),
help = STRING_TOKEN(STR_ISCSI_IP_ADDRESS_HELP),
flags = INTERACTIVE,
key = KEY_TARGET_IP,
minsize = IP_MIN_SIZE,
maxsize = IP_MAX_SIZE,
endstring;
numeric varid = ISCSI_CONFIG_IFR_NVDATA.TargetPort,
prompt = STRING_TOKEN(STR_ISCSI_TARGET_PORT),
help = STRING_TOKEN(STR_ISCSI_TARGET_PORT),
flags = 0,
minimum = TARGET_PORT_MIN_NUM,
maximum = TARGET_PORT_MAX_NUM,
step = 0,
endnumeric;
string varid = ISCSI_CONFIG_IFR_NVDATA.BootLun,
prompt = STRING_TOKEN(STR_ISCSI_BOOT_LUN),
help = STRING_TOKEN(STR_ISCSI_BOOT_LUN_HELP),
flags = INTERACTIVE,
key = KEY_BOOT_LUN,
minsize = LUN_MIN_SIZE,
maxsize = LUN_MAX_SIZE,
endstring;
endif;
subtitle text = STRING_TOKEN(STR_NULL);
oneof varid = ISCSI_CONFIG_IFR_NVDATA.CHAPType,
prompt = STRING_TOKEN(STR_CHAP_TYPE_PROMPT),
help = STRING_TOKEN(STR_CHAP_TYPE_HELP),
option text = STRING_TOKEN(STR_CHAP_TYPE_NONE), value = ISCSI_CHAP_NONE, flags = DEFAULT;
option text = STRING_TOKEN(STR_CHAP_TYPE_UNI), value = ISCSI_CHAP_UNI, flags = 0;
option text = STRING_TOKEN(STR_CHAP_TYPE_MUTUAL), value = ISCSI_CHAP_MUTUAL, flags = 0;
endoneof;
suppressif ideqval ISCSI_CONFIG_IFR_NVDATA.CHAPType == ISCSI_CHAP_NONE;
string varid = ISCSI_CONFIG_IFR_NVDATA.CHAPName,
prompt = STRING_TOKEN(STR_ISCSI_CHAP_NAME),
help = STRING_TOKEN(STR_ISCSI_CHAP_NAME),
flags = INTERACTIVE,
key = KEY_CHAP_NAME,
minsize = 0,
maxsize = ISCSI_CHAP_NAME_MAX_LEN,
endstring;
string varid = ISCSI_CONFIG_IFR_NVDATA.CHAPSecret,
prompt = STRING_TOKEN(STR_ISCSI_CHAP_SECRET),
help = STRING_TOKEN(STR_ISCSI_CHAP_SECRET_HELP),
flags = INTERACTIVE,
key = KEY_CHAP_SECRET,
minsize = ISCSI_CHAP_SECRET_MIN_LEN,
maxsize = ISCSI_CHAP_SECRET_MAX_LEN,
endstring;
endif;
suppressif NOT ideqval ISCSI_CONFIG_IFR_NVDATA.CHAPType == ISCSI_CHAP_MUTUAL;
string varid = ISCSI_CONFIG_IFR_NVDATA.ReverseCHAPName,
prompt = STRING_TOKEN(STR_ISCSI_REVERSE_CHAP_NAME),
help = STRING_TOKEN(STR_ISCSI_REVERSE_CHAP_NAME),
flags = INTERACTIVE,
key = KEY_REVERSE_CHAP_NAME,
minsize = 0,
maxsize = ISCSI_CHAP_NAME_MAX_LEN,
endstring;
string varid = ISCSI_CONFIG_IFR_NVDATA.ReverseCHAPSecret,
prompt = STRING_TOKEN(STR_ISCSI_REVERSE_CHAP_SECRET),
help = STRING_TOKEN(STR_ISCSI_CHAP_SECRET_HELP),
flags = INTERACTIVE,
key = KEY_REVERSE_CHAP_SECRET,
minsize = ISCSI_CHAP_SECRET_MIN_LEN,
maxsize = ISCSI_CHAP_SECRET_MAX_LEN,
endstring;
endif;
subtitle text = STRING_TOKEN(STR_NULL);
goto FORMID_DEVICE_FORM,
prompt = STRING_TOKEN (STR_SAVE_CHANGES),
help = STRING_TOKEN (STR_SAVE_CHANGES),
flags = INTERACTIVE,
key = KEY_SAVE_CHANGES;
goto FORMID_MAIN_FORM,
prompt = STRING_TOKEN (STR_RETURN_MAIN_FORM),
help = STRING_TOKEN (STR_RETURN_MAIN_FORM),
flags = 0;
endform;
endformset;

Binary file not shown.

View File

@ -0,0 +1,104 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiConfigNVDataStruc.h
Abstract:
NVData structure used by the iSCSI configuration component.
--*/
#ifndef _ISCSI_NVDATASTRUC_H_
#define _ISCSI_NVDATASTRUC_H_
#define ISCSI_CONFIG_GUID \
{ \
0x6456ed61, 0x3579, 0x41c9, { 0x8a, 0x26, 0x0a, 0x0b, 0xd6, 0x2b, 0x78, 0xfc } \
}
#define VAR_EQ_TEST_NAME 0x100
#define FORMID_MAIN_FORM 1
#define FORMID_DEVICE_FORM 2
#define ISCSI_NAME_MAX_SIZE 224
//
// Vfr has a limit on the size, it's 255 bytes.
//
#define ISCSI_NAME_IFR_MAX_SIZE 126
#define IP_MIN_SIZE 7
#define IP_MAX_SIZE 15
#define IP4_STR_MAX_SIZE 16
#define LUN_MIN_SIZE 1
#define LUN_MAX_SIZE 20
#define ISCSI_CHAP_NONE 0
#define ISCSI_CHAP_UNI 1
#define ISCSI_CHAP_MUTUAL 2
#define TARGET_PORT_MIN_NUM 0
#define TARGET_PORT_MAX_NUM 65535
#define DEVICE_ENTRY_LABEL 0x1234
#define KEY_INITIATOR_NAME 0x01
#define KEY_DHCP_ENABLE 0x02
#define KEY_LOCAL_IP 0x03
#define KEY_SUBNET_MASK 0x04
#define KEY_GATE_WAY 0x05
#define KEY_TARGET_IP 0x06
#define KEY_CHAP_NAME 0x07
#define KEY_CHAP_SECRET 0x08
#define KEY_REVERSE_CHAP_NAME 0x09
#define KEY_REVERSE_CHAP_SECRET 0x0a
#define KEY_SAVE_CHANGES 0x0b
#define KEY_TARGET_NAME 0x0c
#define KEY_BOOT_LUN 0x0d
#define KEY_DEVICE_ENTRY_BASE 0x1000
#define ISCSI_LUN_STR_MAX_LEN 21
#define ISCSI_CHAP_SECRET_MIN_LEN 13
#define ISCSI_CHAP_SECRET_MAX_LEN 17
#define ISCSI_CHAP_NAME_MAX_LEN 126
#pragma pack(1)
typedef struct {
CHAR16 InitiatorName[ISCSI_NAME_IFR_MAX_SIZE];
UINT8 Enabled;
UINT8 InitiatorInfoFromDhcp;
CHAR16 LocalIp[IP4_STR_MAX_SIZE];
CHAR16 SubnetMask[IP4_STR_MAX_SIZE];
CHAR16 Gateway[IP4_STR_MAX_SIZE];
CHAR16 TargetName[ISCSI_NAME_IFR_MAX_SIZE];
CHAR16 TargetIp[IP4_STR_MAX_SIZE];
UINT16 TargetPort;
CHAR16 BootLun[ISCSI_LUN_STR_MAX_LEN];
UINT8 TargetInfoFromDhcp;
UINT8 CHAPType;
CHAR16 CHAPName[ISCSI_CHAP_NAME_MAX_LEN];
CHAR16 CHAPSecret[ISCSI_CHAP_SECRET_MAX_LEN];
CHAR16 ReverseCHAPName[ISCSI_CHAP_NAME_MAX_LEN];
CHAR16 ReverseCHAPSecret[ISCSI_CHAP_SECRET_MAX_LEN];
} ISCSI_CONFIG_IFR_NVDATA;
#pragma pack()
#endif

View File

@ -0,0 +1,498 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiDhcp.c
Abstract:
iSCSI DHCP related configuration routines.
--*/
#include "IScsiImpl.h"
STATIC
EFI_STATUS
IScsiDhcpExtractRootPath (
IN CHAR8 *RootPath,
IN UINT8 Length,
IN ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData
)
/*++
Routine Description:
Extract the Root Path option and get the required target information.
Arguments:
RootPath - The RootPath.
Length - Length of the RootPath option payload.
ConfigNvData - The iSCSI session configuration data read from nonvolatile device.
Returns:
EFI_SUCCESS - All required information is extracted from the RootPath option.
EFI_NOT_FOUND - The RootPath is not an iSCSI RootPath.
EFI_OUT_OF_RESOURCES - Failed to allocate memory.
EFI_INVALID_PARAMETER - The RootPath is mal-formatted.
--*/
{
EFI_STATUS Status;
UINT8 IScsiRootPathIdLen;
CHAR8 *TmpStr;
ISCSI_ROOT_PATH_FIELD Fields[RP_FIELD_IDX_MAX];
ISCSI_ROOT_PATH_FIELD *Field;
UINT32 FieldIndex;
UINT8 Index;
//
// "iscsi:"<servername>":"<protocol>":"<port>":"<LUN>":"<targetname>
//
IScsiRootPathIdLen = (UINT8) AsciiStrLen (ISCSI_ROOT_PATH_ID);
if ((Length <= IScsiRootPathIdLen) || (NetCompareMem (RootPath, ISCSI_ROOT_PATH_ID, IScsiRootPathIdLen) != 0)) {
return EFI_NOT_FOUND;
}
//
// Skip the iSCSI RootPath ID "iscsi:".
//
RootPath += IScsiRootPathIdLen;
Length = (UINT8) (Length - IScsiRootPathIdLen);
TmpStr = (CHAR8 *) NetAllocatePool (Length + 1);
if (TmpStr == NULL) {
return EFI_OUT_OF_RESOURCES;
}
NetCopyMem (TmpStr, RootPath, Length);
TmpStr[Length] = '\0';
Index = 0;
FieldIndex = 0;
NetZeroMem (&Fields[0], sizeof (Fields));
//
// Extract the fields in the Root Path option string.
//
for (FieldIndex = 0; (FieldIndex < RP_FIELD_IDX_MAX) && (Index < Length); FieldIndex++) {
if (TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) {
Fields[FieldIndex].Str = &TmpStr[Index];
}
while ((TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) && (Index < Length)) {
Index++;
}
if (TmpStr[Index] == ISCSI_ROOT_PATH_FIELD_DELIMITER) {
if (FieldIndex != RP_FIELD_IDX_TARGETNAME) {
TmpStr[Index] = '\0';
Index++;
}
if (Fields[FieldIndex].Str != NULL) {
Fields[FieldIndex].Len = (UINT8) AsciiStrLen (Fields[FieldIndex].Str);
}
}
}
if (FieldIndex != RP_FIELD_IDX_MAX) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if ((Fields[RP_FIELD_IDX_SERVERNAME].Str == NULL) ||
(Fields[RP_FIELD_IDX_TARGETNAME].Str == NULL) ||
(Fields[RP_FIELD_IDX_PROTOCOL].Len > 1)
) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
//
// Get the IP address of the target.
//
Field = &Fields[RP_FIELD_IDX_SERVERNAME];
Status = IScsiAsciiStrToIp (Field->Str, &ConfigNvData->TargetIp);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Check the protocol type.
//
Field = &Fields[RP_FIELD_IDX_PROTOCOL];
if ((Field->Str != NULL) && ((*(Field->Str) - '0') != EFI_IP_PROTO_TCP)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
//
// Get the port of the iSCSI target.
//
Field = &Fields[RP_FIELD_IDX_PORT];
if (Field->Str != NULL) {
ConfigNvData->TargetPort = (UINT16) AsciiStrDecimalToUintn (Field->Str);
} else {
ConfigNvData->TargetPort = ISCSI_WELL_KNOWN_PORT;
}
//
// Get the LUN.
//
Field = &Fields[RP_FIELD_IDX_LUN];
if (Field->Str != NULL) {
Status = IScsiAsciiStrToLun (Field->Str, ConfigNvData->BootLun);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
} else {
NetZeroMem (ConfigNvData->BootLun, sizeof (ConfigNvData->BootLun));
}
//
// Get the target iSCSI Name.
//
Field = &Fields[RP_FIELD_IDX_TARGETNAME];
if (AsciiStrLen (Field->Str) > ISCSI_NAME_MAX_SIZE - 1) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
//
// Validate the iSCSI name.
//
Status = IScsiNormalizeName (Field->Str, AsciiStrLen (Field->Str));
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
AsciiStrCpy (ConfigNvData->TargetName, Field->Str);
ON_EXIT:
NetFreePool (TmpStr);
return Status;
}
STATIC
EFI_STATUS
IScsiDhcpSelectOffer (
IN EFI_DHCP4_PROTOCOL * This,
IN VOID *Context,
IN EFI_DHCP4_STATE CurrentState,
IN EFI_DHCP4_EVENT Dhcp4Event,
IN EFI_DHCP4_PACKET * Packet, OPTIONAL
OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL
)
/*++
Routine Description:
The callback function registerd to the DHCP4 instance which is used to select
the qualified DHCP OFFER.
Arguments:
This - The DHCP4 protocol.
Context - The context set when configuring the DHCP4 protocol.
CurrentState - The current state of the DHCP4 protocol.
Dhcp4Event - The event occurs in the current state.
Packet - The DHCP packet that is to be sent or already received.
NewPackt - The packet used to replace the above Packet.
Returns:
EFI_NOT_READY - The DHCP OFFER packet doesn't match our requirements.
EFI_SUCCESS - Either the DHCP OFFER is qualified or we're not intereseted
in the Dhcp4Event.
--*/
{
EFI_STATUS Status;
UINT32 OptionCount;
EFI_DHCP4_PACKET_OPTION **OptionList;
UINT32 Index;
if ((Dhcp4Event != Dhcp4RcvdOffer) && (Dhcp4Event != Dhcp4SelectOffer)) {
return EFI_SUCCESS;
}
OptionCount = 0;
Status = This->Parse (This, Packet, &OptionCount, NULL);
if (Status != EFI_BUFFER_TOO_SMALL) {
return EFI_NOT_READY;
}
OptionList = NetAllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
if (OptionList == NULL) {
return EFI_NOT_READY;
}
Status = This->Parse (This, Packet, &OptionCount, OptionList);
if (EFI_ERROR (Status)) {
NetFreePool (OptionList);
return EFI_NOT_READY;
}
for (Index = 0; Index < OptionCount; Index++) {
if (OptionList[Index]->OpCode != DHCP4_TAG_ROOT_PATH) {
continue;
}
Status = IScsiDhcpExtractRootPath (
(CHAR8 *) &OptionList[Index]->Data[0],
OptionList[Index]->Length,
(ISCSI_SESSION_CONFIG_NVDATA *) Context
);
break;
}
if ((Index == OptionCount)) {
Status = EFI_NOT_READY;
}
NetFreePool (OptionList);
return Status;
}
EFI_STATUS
IScsiParseDhcpAck (
IN EFI_DHCP4_PROTOCOL *Dhcp4,
IN ISCSI_SESSION_CONFIG_DATA *ConfigData
)
/*++
Routine Description:
Parse the DHCP ACK to get the address configuration and DNS information.
Arguments:
Dhcp4 - The DHCP4 protocol.
ConfigData - The session configuration data.
Returns:
EFI_SUCCESS - The DNS information is got from the DHCP ACK.
EFI_NO_MAPPING - DHCP failed to acquire address and other information.
EFI_INVALID_PARAMETER - The DHCP ACK's DNS option is mal-formatted.
EFI_DEVICE_ERROR - Some unexpected error happened.
--*/
{
EFI_STATUS Status;
EFI_DHCP4_MODE_DATA Dhcp4ModeData;
UINT32 OptionCount;
EFI_DHCP4_PACKET_OPTION **OptionList;
UINT32 Index;
Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4ModeData);
if (EFI_ERROR (Status)) {
return Status;
}
if (Dhcp4ModeData.State != Dhcp4Bound) {
return EFI_NO_MAPPING;
}
NetCopyMem (&ConfigData->NvData.LocalIp, &Dhcp4ModeData.ClientAddress, sizeof (EFI_IPv4_ADDRESS));
NetCopyMem (&ConfigData->NvData.SubnetMask, &Dhcp4ModeData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
NetCopyMem (&ConfigData->NvData.Gateway, &Dhcp4ModeData.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
OptionCount = 0;
OptionList = NULL;
Status = Dhcp4->Parse (Dhcp4, Dhcp4ModeData.ReplyPacket, &OptionCount, OptionList);
if (Status != EFI_BUFFER_TOO_SMALL) {
return EFI_DEVICE_ERROR;
}
OptionList = NetAllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
if (OptionList == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = Dhcp4->Parse (Dhcp4, Dhcp4ModeData.ReplyPacket, &OptionCount, OptionList);
if (EFI_ERROR (Status)) {
NetFreePool (OptionList);
return EFI_DEVICE_ERROR;
}
for (Index = 0; Index < OptionCount; Index++) {
//
// Get DNS server addresses and DHCP server address from this offer.
//
if (OptionList[Index]->OpCode == DHCP4_TAG_DNS) {
if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {
Status = EFI_INVALID_PARAMETER;
break;
}
//
// Primary DNS server address.
//
NetCopyMem (&ConfigData->PrimaryDns, &OptionList[Index]->Data[0], sizeof (EFI_IPv4_ADDRESS));
if (OptionList[Index]->Length > 4) {
//
// Secondary DNS server address
//
NetCopyMem (&ConfigData->SecondaryDns, &OptionList[Index]->Data[4], sizeof (EFI_IPv4_ADDRESS));
}
} else if (OptionList[Index]->OpCode == DHCP4_TAG_SERVER_ID) {
if (OptionList[Index]->Length != 4) {
Status = EFI_INVALID_PARAMETER;
break;
}
NetCopyMem (&ConfigData->DhcpServer, &OptionList[Index]->Data[0], sizeof (EFI_IPv4_ADDRESS));
}
}
NetFreePool (OptionList);
return Status;
}
EFI_STATUS
IScsiDoDhcp (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller,
IN ISCSI_SESSION_CONFIG_DATA *ConfigData
)
/*++
Routine Description:
Parse the DHCP ACK to get the address configuration and DNS information.
Arguments:
Image - The handle of the driver image.
Controller - The handle of the controller;
ConfigData - The session configuration data.
Returns:
EFI_SUCCESS - The DNS information is got from the DHCP ACK.
EFI_NO_MAPPING - DHCP failed to acquire address and other information.
EFI_INVALID_PARAMETER - The DHCP ACK's DNS option is mal-formatted.
EFI_DEVICE_ERROR - Some unexpected error happened.
--*/
{
EFI_HANDLE Dhcp4Handle;
EFI_DHCP4_PROTOCOL *Dhcp4;
EFI_STATUS Status;
EFI_DHCP4_PACKET_OPTION *ParaList;
EFI_DHCP4_CONFIG_DATA Dhcp4ConfigData;
Dhcp4Handle = NULL;
Dhcp4 = NULL;
ParaList = NULL;
//
// Create a DHCP4 child instance and get the protocol.
//
Status = NetLibCreateServiceChild (
Controller,
Image,
&gEfiDhcp4ServiceBindingProtocolGuid,
&Dhcp4Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->OpenProtocol (
Dhcp4Handle,
&gEfiDhcp4ProtocolGuid,
(VOID **)&Dhcp4,
Image,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
ParaList = NetAllocatePool (sizeof (EFI_DHCP4_PACKET_OPTION) + 3);
if (ParaList == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Ask the server to reply with Netmask, Router, DNS and RootPath options.
//
ParaList->OpCode = DHCP4_TAG_PARA_LIST;
ParaList->Length = ConfigData->NvData.TargetInfoFromDhcp ? 4 : 3;
ParaList->Data[0] = DHCP4_TAG_NETMASK;
ParaList->Data[1] = DHCP4_TAG_ROUTER;
ParaList->Data[2] = DHCP4_TAG_DNS;
ParaList->Data[3] = DHCP4_TAG_ROOT_PATH;
NetZeroMem (&Dhcp4ConfigData, sizeof (EFI_DHCP4_CONFIG_DATA));
Dhcp4ConfigData.OptionCount = 1;
Dhcp4ConfigData.OptionList = &ParaList;
if (ConfigData->NvData.TargetInfoFromDhcp) {
//
// Use callback to select an offer which contains target information.
//
Dhcp4ConfigData.Dhcp4Callback = IScsiDhcpSelectOffer;
Dhcp4ConfigData.CallbackContext = &ConfigData->NvData;
}
Status = Dhcp4->Configure (Dhcp4, &Dhcp4ConfigData);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
Status = Dhcp4->Start (Dhcp4, NULL);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Parse the ACK to get required information.
//
Status = IScsiParseDhcpAck (Dhcp4, ConfigData);
ON_EXIT:
if (ParaList != NULL) {
NetFreePool (ParaList);
}
if (Dhcp4 != NULL) {
Dhcp4->Stop (Dhcp4);
Dhcp4->Configure (Dhcp4, NULL);
gBS->CloseProtocol (
Dhcp4Handle,
&gEfiDhcp4ProtocolGuid,
Image,
Controller
);
}
NetLibDestroyServiceChild (
Controller,
Image,
&gEfiDhcp4ServiceBindingProtocolGuid,
Dhcp4Handle
);
return Status;
}

View File

@ -0,0 +1,57 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiDhcp.h
Abstract:
--*/
#ifndef _ISCSI_DHCP_H_
#define _ISCSI_DHCP_H_
//#include "Tiano.h"
//#include EFI_PROTOCOL_CONSUMER (Dhcp4)
#include "protocol\Dhcp4.h"
#define DHCP4_TAG_PARA_LIST 55
#define DHCP4_TAG_NETMASK 1
#define DHCP4_TAG_ROUTER 3
#define DHCP4_TAG_DNS 6
#define DHCP4_TAG_SERVER_ID 54
#define DHCP4_TAG_ROOT_PATH 17
#define ISCSI_ROOT_PATH_ID "iscsi:"
#define ISCSI_ROOT_PATH_FIELD_DELIMITER ':'
enum {
RP_FIELD_IDX_SERVERNAME = 0,
RP_FIELD_IDX_PROTOCOL,
RP_FIELD_IDX_PORT,
RP_FIELD_IDX_LUN,
RP_FIELD_IDX_TARGETNAME,
RP_FIELD_IDX_MAX
};
typedef struct _ISCSI_ROOT_PATH_FIELD {
CHAR8 *Str;
UINT8 Len;
} ISCSI_ROOT_PATH_FIELD;
EFI_STATUS
IScsiDoDhcp (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller,
IN ISCSI_SESSION_CONFIG_DATA *ConfigData
);
#endif

View File

@ -0,0 +1,462 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiDriver.c
Abstract:
--*/
#include "IScsiImpl.h"
EFI_DRIVER_BINDING_PROTOCOL gIScsiDriverBinding = {
IScsiDriverBindingSupported,
IScsiDriverBindingStart,
IScsiDriverBindingStop,
0xa,
NULL,
NULL
};
EFI_GUID mIScsiPrivateGuid = ISCSI_PRIVATE_GUID;
EFI_STATUS
EFIAPI
IScsiDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
/*++
Routine Description:
Test to see if iSCSI driver supports the given controller.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of controller to test.
RemainingDevicePath - Optional parameter use to pick a specific child device to start.
Returns:
EFI_SUCCES - This driver supports the controller.
EFI_ALREADY_STARTED - This driver is already running on this device.
EFI_UNSUPPORTED - This driver doesn't support the controller.
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath;
Status = gBS->OpenProtocol (
ControllerHandle,
&mIScsiPrivateGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
CurrentDevicePath = RemainingDevicePath;
if (CurrentDevicePath != NULL) {
while (!IsDevicePathEnd (CurrentDevicePath)) {
if ((CurrentDevicePath->Type == MESSAGING_DEVICE_PATH) && (CurrentDevicePath->SubType == MSG_ISCSI_DP)) {
return EFI_SUCCESS;
}
CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);
}
return EFI_UNSUPPORTED;
}
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IScsiDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
/*++
Routine Description:
Start to manage the controller.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of the controller.
RemainingDevicePath - Optional parameter use to pick a specific child device to start.
Returns:
EFI_SUCCES - This driver supports this device.
EFI_ALREADY_STARTED - This driver is already running on this device.
--*/
{
EFI_STATUS Status;
ISCSI_DRIVER_DATA *Private;
//
// Try to add a port configuration page for this controller.
//
IScsiConfigUpdateForm (This->DriverBindingHandle, ControllerHandle, TRUE);
Private = IScsiCreateDriverData (This->DriverBindingHandle, ControllerHandle);
if (Private == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Get the iSCSI configuration data of this controller.
//
Status = IScsiGetConfigData (Private);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Try to login and create an iSCSI session according to the configuration.
//
Status = IScsiSessionLogin (Private);
if (Status == EFI_MEDIA_CHANGED) {
//
// The specified target is not available and the redirection information is
// got, login the session again with the updated target address.
//
Status = IScsiSessionLogin (Private);
}
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Duplicate the Session's tcp connection device path. The source port field
// will be set to zero as one iSCSI session is comprised of several iSCSI
// connections.
//
Private->DevicePath = IScsiGetTcpConnDevicePath (Private);
if (Private->DevicePath == NULL) {
goto ON_ERROR;
}
//
// Install the updated device path onto the ExtScsiPassThruHandle.
//
Status = gBS->InstallProtocolInterface (
&Private->ExtScsiPassThruHandle,
&gEfiDevicePathProtocolGuid,
EFI_NATIVE_INTERFACE,
Private->DevicePath
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Install the iSCSI private stuff as a flag to indicate this controller
// is already controlled by iSCSI driver.
//
Status = gBS->InstallProtocolInterface (
&ControllerHandle,
&mIScsiPrivateGuid,
EFI_NATIVE_INTERFACE,
&Private->IScsiIdentifier
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
//
// Update/Publish the iSCSI Boot Firmware Table.
//
IScsiPublishIbft ();
return EFI_SUCCESS;
ON_ERROR:
IScsiSessionAbort (&Private->Session);
IScsiCleanDriverData (Private);
return Status;
}
EFI_STATUS
EFIAPI
IScsiDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
/*++
Routine Description:
Release the control of this controller and remove the iSCSI functions.
Arguments:
This - Protocol instance pointer.
ControllerHandle - Handle of controller to stop.
NumberOfChildren - Not used.
ChildHandleBuffer - Not used.
Returns:
EFI_SUCCES - This driver supports this device.
--*/
{
EFI_HANDLE IScsiController;
EFI_STATUS Status;
ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
ISCSI_DRIVER_DATA *Private;
EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru;
ISCSI_CONNECTION *Conn;
if (NumberOfChildren != 0) {
//
// We should have only one child.
//
Status = gBS->OpenProtocol (
ChildHandleBuffer[0],
&gEfiExtScsiPassThruProtocolGuid,
(VOID **) &PassThru,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
Conn = NET_LIST_HEAD (&Private->Session.Conns, ISCSI_CONNECTION, Link);
//
// Previously the TCP4 protocol is opened BY_CHILD_CONTROLLER. Just close
// the protocol here but not uninstall the device path protocol and
// EXT SCSI PASS THRU protocol installed on ExtScsiPassThruHandle.
//
gBS->CloseProtocol (
Conn->Tcp4Io.Handle,
&gEfiTcp4ProtocolGuid,
Private->Image,
Private->ExtScsiPassThruHandle
);
return EFI_SUCCESS;
}
//
// Get the handle of the controller we are controling.
//
IScsiController = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
Status = gBS->OpenProtocol (
IScsiController,
&mIScsiPrivateGuid,
(VOID **)&IScsiIdentifier,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Private = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
//
// Uninstall the private protocol.
//
gBS->UninstallProtocolInterface (
IScsiController,
&mIScsiPrivateGuid,
&Private->IScsiIdentifier
);
//
// Update the iSCSI Boot Firware Table.
//
IScsiPublishIbft ();
IScsiSessionAbort (&Private->Session);
IScsiCleanDriverData (Private);
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
EfiIScsiUnload (
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Unload the iSCSI driver.
Arguments:
ImageHandle - The handle of the driver image.
Returns:
EFI_SUCCESS - The driver is unloaded.
EFI_DEVICE_ERROR - Some unexpected error happened.
--*/
{
EFI_STATUS Status;
UINTN DeviceHandleCount;
EFI_HANDLE *DeviceHandleBuffer;
UINTN Index;
//
// Try to disonnect the driver from the devices it's controlling.
//
Status = gBS->LocateHandleBuffer (
AllHandles,
NULL,
NULL,
&DeviceHandleCount,
&DeviceHandleBuffer
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < DeviceHandleCount; Index++) {
Status = gBS->DisconnectController (
DeviceHandleBuffer[Index],
ImageHandle,
NULL
);
}
if (DeviceHandleBuffer != NULL) {
NetFreePool (DeviceHandleBuffer);
}
}
//
// Unload the iSCSI configuration form.
//
IScsiConfigFormUnload (gIScsiDriverBinding.DriverBindingHandle);
//
// Uninstall the protocols installed by iSCSI driver.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiDriverBindingProtocolGuid,
&gIScsiDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gIScsiComponentName2,
&gEfiComponentNameProtocolGuid,
&gIScsiComponentName,
&gEfiIScsiInitiatorNameProtocolGuid,
&gIScsiInitiatorName,
NULL
);
return Status;
}
EFI_STATUS
EFIAPI
IScsiDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
Initialize the global variables publish the driver binding protocol.
Arguments:
ImageHandle - The handle of the driver image.
SystemTable - The EFI system table.
Returns:
EFI_SUCCESS - The protocols are installed.
EFI_DEVICE_ERROR - Some unexpected error happened.
--*/
{
EFI_STATUS Status;
//EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
//
// Initialize the EFI Driver Library
//
Status = EfiLibInstallDriverBindingComponentName2 (
ImageHandle,
SystemTable,
&gIScsiDriverBinding,
ImageHandle,
&gIScsiComponentName,
&gIScsiComponentName2
);
if (EFI_ERROR (Status)) {
return Status;
}
if (!EFI_ERROR (Status)) {
Status = gBS->InstallProtocolInterface (
&ImageHandle,
&gEfiIScsiInitiatorNameProtocolGuid,
EFI_NATIVE_INTERFACE,
&gIScsiInitiatorName
);
if (EFI_ERROR (Status)) {
gBS->UninstallMultipleProtocolInterfaces (
ImageHandle,
&gEfiDriverBindingProtocolGuid,
&gIScsiDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gIScsiComponentName2,
&gEfiComponentNameProtocolGuid,
&gIScsiComponentName,
NULL
);
}
}
//
// Initialize the configuration form of iSCSI.
//
IScsiConfigFormInit (gIScsiDriverBinding.DriverBindingHandle);
return Status;
}

View File

@ -0,0 +1,123 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiDriver.h
Abstract:
--*/
#ifndef _ISCSI_DRIVER_H_
#define _ISCSI_DRIVER_H_
#include <PiDxe.h>
#include <Protocol/DevicePath.h>
#include <Protocol/LoadedImage.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/DevicePathLib.h>
#include <protocol/DriverBinding.h>
#include <protocol/ScsiPassThruExt.h>
#include <protocol/IScsiInitiatorName.h>
#include <protocol/Ip4Config.h>
#include <protocol/ComponentName.h>
#include <protocol/ComponentName2.h>
#define ISCSI_PRIVATE_GUID \
{ \
0xfa3cde4c, 0x87c2, 0x427d, 0xae, 0xde, 0x7d, 0xd0, 0x96, 0xc8, 0x8c, 0x58 \
}
#define ISCSI_INITIATOR_NAME_VAR_NAME L"I_NAME"
extern EFI_COMPONENT_NAME2_PROTOCOL gIScsiComponentName2;
extern EFI_COMPONENT_NAME_PROTOCOL gIScsiComponentName;
extern EFI_ISCSI_INITIATOR_NAME_PROTOCOL gIScsiInitiatorName;
extern EFI_GUID mIScsiPrivateGuid;
typedef struct _ISCSI_PRIVATE_PROTOCOL {
UINT32 Reserved;
} ISCSI_PRIVATE_PROTOCOL;
//
// EFI Driver Binding Protocol for iSCSI driver.
//
EFI_STATUS
EFIAPI
IScsiDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
IScsiDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
IScsiDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// EFI Component Name Protocol for iSCSI driver.
//
EFI_STATUS
EFIAPI
IScsiComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
IScsiComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
//
// EFI iSCSI Initiator Name Protocol for iSCSI driver.
//
EFI_STATUS
EFIAPI
IScsiGetInitiatorName (
IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
EFI_STATUS
EFIAPI
IScsiSetInitiatorName (
IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
);
#endif

View File

@ -0,0 +1,401 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiExtScsiPassThru.c
Abstract:
--*/
#include "IScsiImpl.h"
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruFunction (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN UINT8 *Target,
IN UINT64 Lun,
IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
IN EFI_EVENT Event OPTIONAL
)
/*++
Routine Description:
This function sends out the SCSI command via iSCSI transport layer and returned
back the data received from the iSCSI target.
Arguments:
This - The EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
Target - The Target ID of device to send the SCSI Request Packet.
Lun - The LUN of the device to send the SCSI Request Packet.
Packet - The SCSI Request Packet to send to the device.
Event - The event used in non-blocking mode, it should be always NULL.
Returns:
EFI_STATUS
--*/
{
if (Target[0] != 0) {
return EFI_INVALID_PARAMETER;
}
if ((Packet == NULL) || (Packet->Cdb == NULL)) {
return EFI_INVALID_PARAMETER;
}
return IScsiExecuteScsiCommand (This, Target, Lun, Packet);
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruGetNextTargetLun (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN OUT UINT8 **Target,
IN OUT UINT64 *Lun
)
/*++
Routine Description:
Retrieve the list of legal Target IDs for SCSI devices on a SCSI channel.
Arguments:
This - The EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance..
Target - On input, a pointer to the Target ID of a SCSI device present on the
SCSI channel. On output, a pointer to the Target ID of the next SCSI
device present on a SCSI channel. An input value of 0xFFFFFFFF
retrieves the Target ID of the first SCSI device present on a SCSI channel.
Lun - On input, a pointer to the LUN of a SCSI device present on the SCSI
channel. On output, a pointer to the LUN of the next SCSI device present on
a SCSI channel.
Returns:
EFI_SUCCESS - The Target ID and Lun of the next SCSI device
on the SCSI channel was returned in Target and Lun.
EFI_NOT_FOUND - There are no more SCSI devices on this SCSI channel.
EFI_INVALID_PARAMETER - Target is not 0xFFFFFFFF,and Target and Lun were not
returned on a previous call to GetNextDevice().
--*/
{
ISCSI_DRIVER_DATA *Private;
ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;
UINT8 TargetId[TARGET_MAX_BYTES];
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);
ConfigNvData = &Private->Session.ConfigData.NvData;
if ((*Target)[0] == 0 && (NetCompareMem (Lun, ConfigNvData->BootLun, sizeof (UINT64)) == 0)) {
//
// Only one <Target, Lun> pair per iSCSI Driver instance.
//
return EFI_NOT_FOUND;
}
NetSetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
if (NetCompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) {
(*Target)[0] = 0;
NetCopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64));
return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruBuildDevicePath (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN UINT8 *Target,
IN UINT64 Lun,
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
)
/*++
Routine Description:
Allocate and build a device path node for a SCSI device on a SCSI channel.
Arguments:
This - Protocol instance pointer.
Target - The Target ID of the SCSI device for which
a device path node is to be allocated and built.
Lun - The LUN of the SCSI device for which a device
path node is to be allocated and built.
DevicePath - A pointer to a single device path node that
describes the SCSI device specified by
Target and Lun. This function is responsible
for allocating the buffer DevicePath with the boot
service AllocatePool(). It is the caller's
responsibility to free DevicePath when the caller
is finished with DevicePath.
Returns:
EFI_SUCCESS - The device path node that describes the SCSI device
specified by Target and Lun was allocated and
returned in DevicePath.
EFI_NOT_FOUND - The SCSI devices specified by Target and Lun does
not exist on the SCSI channel.
EFI_INVALID_PARAMETER - DevicePath is NULL.
EFI_OUT_OF_RESOURCES - There are not enough resources to allocate
DevicePath.
--*/
{
ISCSI_DRIVER_DATA *Private;
ISCSI_SESSION *Session;
ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;
ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
EFI_DEV_PATH *Node;
UINTN DevPathNodeLen;
if ((DevicePath == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Target[0] != 0) {
return EFI_NOT_FOUND;
}
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);
Session = &Private->Session;
ConfigNvData = &Session->ConfigData.NvData;
AuthConfig = &Session->AuthData.AuthConfig;
if (NetCompareMem (&Lun, ConfigNvData->BootLun, sizeof (UINT64)) != 0) {
return EFI_NOT_FOUND;
}
DevPathNodeLen = sizeof (ISCSI_DEVICE_PATH) + AsciiStrLen (ConfigNvData->TargetName) + 1;
Node = NetAllocatePool (DevPathNodeLen);
if (Node == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Node->DevPath.Type = MESSAGING_DEVICE_PATH;
Node->DevPath.SubType = MSG_ISCSI_DP;
SetDevicePathNodeLength (&Node->DevPath, DevPathNodeLen);
//
// 0 for TCP, others are reserved.
//
Node->Iscsi.NetworkProtocol = 0;
Node->Iscsi.LoginOption = 0;
switch (AuthConfig->CHAPType) {
case ISCSI_CHAP_NONE:
Node->Iscsi.LoginOption |= 0x0800;
break;
case ISCSI_CHAP_UNI:
Node->Iscsi.LoginOption |= 0x1000;
break;
default:
break;
}
NetCopyMem (&Node->Iscsi.Lun, ConfigNvData->BootLun, sizeof (UINT64));
Node->Iscsi.TargetPortalGroupTag = Session->TargetPortalGroupTag;
AsciiStrCpy ((CHAR8 *) Node + sizeof (ISCSI_DEVICE_PATH), ConfigNvData->TargetName);
*DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node;
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruGetTargetLun (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
OUT UINT8 **Target,
OUT UINT64 *Lun
)
/*++
Routine Description:
Translate a device path node to a Target ID and LUN.
Arguments:
This - Protocol instance pointer.
DevicePath - A pointer to the device path node that
describes a SCSI device on the SCSI channel.
Target - A pointer to the Target ID of a SCSI device
on the SCSI channel.
Lun - A pointer to the LUN of a SCSI device on
the SCSI channel.
Returns:
EFI_SUCCESS - DevicePath was successfully translated to a
Target ID and LUN, and they were returned
in Target and Lun.
EFI_INVALID_PARAMETER - DevicePath/Target/Lun is NULL.
EFI_UNSUPPORTED - This driver does not support the device path
node type in DevicePath.
EFI_NOT_FOUND - A valid translation from DevicePath to a
Target ID and LUN does not exist.
--*/
{
ISCSI_DRIVER_DATA *Private;
ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;
if ((DevicePath == NULL) || (Target == NULL) || (Lun == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((DevicePath->Type != MESSAGING_DEVICE_PATH) ||
(DevicePath->SubType != MSG_ISCSI_DP) ||
(DevicePathNodeLength (DevicePath) <= sizeof (ISCSI_DEVICE_PATH))
) {
return EFI_UNSUPPORTED;
}
Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (This);
ConfigNvData = &Private->Session.ConfigData.NvData;
NetZeroMem (*Target, TARGET_MAX_BYTES);
if (AsciiStrCmp (ConfigNvData->TargetName, (CHAR8 *) DevicePath + sizeof (ISCSI_DEVICE_PATH)) != 0) {
return EFI_UNSUPPORTED;
}
NetCopyMem (Lun, ConfigNvData->BootLun, sizeof (UINT64));
return EFI_SUCCESS;
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruResetChannel (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
)
/*++
Routine Description:
Resets a SCSI channel.This operation resets all the SCSI devices connected to
the SCSI channel.
Arguments:
This - Protocol instance pointer.
Returns:
EFI_UNSUPPORTED - It's not supported.
--*/
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruResetTargetLun (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN UINT8 *Target,
IN UINT64 Lun
)
/*++
Routine Description:
Resets a SCSI device that is connected to a SCSI channel.
Arguments:
This - Protocol instance pointer.
Target - The Target ID of the SCSI device to reset.
Lun - The LUN of the SCSI device to reset.
Returns:
EFI_UNSUPPORTED - It's not supported.
--*/
{
return EFI_UNSUPPORTED;
}
EFI_STATUS
EFIAPI
IScsiExtScsiPassThruGetNextTarget (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN OUT UINT8 **Target
)
/*++
Routine Description:
Retrieve the list of legal Target IDs for SCSI devices on a SCSI channel.
Arguments:
This - Protocol instance pointer.
Target - On input, a pointer to the Target ID of a SCSI
device present on the SCSI channel. On output,
a pointer to the Target ID of the next SCSI device
present on a SCSI channel. An input value of
0xFFFFFFFF retrieves the Target ID of the first
SCSI device present on a SCSI channel.
Lun - On input, a pointer to the LUN of a SCSI device
present on the SCSI channel. On output, a pointer
to the LUN of the next SCSI device present on
a SCSI channel.
Returns:
EFI_SUCCESS - The Target ID and Lun of the next SCSI device
on the SCSI channel was returned in Target and Lun.
EFI_NOT_FOUND - There are no more SCSI devices on this SCSI channel.
EFI_INVALID_PARAMETER - Target is not 0xFFFFFFFF,and Target and Lun were not
returned on a previous call to GetNextDevice().
--*/
{
UINT8 TargetId[TARGET_MAX_BYTES];
NetSetMem (TargetId, TARGET_MAX_BYTES, 0xFF);
if (NetCompareMem (*Target, TargetId, TARGET_MAX_BYTES) == 0) {
(*Target)[0] = 0;
return EFI_SUCCESS;
} else if ((*Target)[0] == 0) {
return EFI_NOT_FOUND;
} else {
return EFI_INVALID_PARAMETER;
}
}
EFI_EXT_SCSI_PASS_THRU_PROTOCOL gIScsiExtScsiPassThruProtocolTemplate = {
NULL,
IScsiExtScsiPassThruFunction,
IScsiExtScsiPassThruGetNextTargetLun,
IScsiExtScsiPassThruBuildDevicePath,
IScsiExtScsiPassThruGetTargetLun,
IScsiExtScsiPassThruResetChannel,
IScsiExtScsiPassThruResetTargetLun,
IScsiExtScsiPassThruGetNextTarget
};

View File

@ -0,0 +1,27 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiExtScsiPassThru.h
Abstract:
--*/
#ifndef _ISCSI_EXT_SCSI_PASS_THRU_H_
#define _ISCSI_EXT_SCSI_PASS_THRU_H_
#include <protocol/ScsiPassThruExt.h>
extern EFI_EXT_SCSI_PASS_THRU_PROTOCOL gIScsiExtScsiPassThruProtocolTemplate;
#endif

View File

@ -0,0 +1,645 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiIbft.c
Abstract:
Implementation for iSCSI Boot Firmware Table publication.
--*/
#include "IScsiImpl.h"
STATIC
VOID
IScsiInitIbfTableHeader (
IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Header
)
/*++
Routine Description:
Initialize the header of the iSCSI Boot Firmware Table.
Arguments:
Header - The header of the iSCSI Boot Firmware Table.
Returns:
None.
--*/
{
NetZeroMem (Header, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER));
Header->Signature = EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE;
Header->Length = IBFT_HEAP_OFFSET;
Header->Revision = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_REVISION;
Header->Checksum = 0;
Header->OemId[0] = 'I';
Header->OemId[1] = 'N';
Header->OemId[2] = 'T';
Header->OemId[3] = 'E';
Header->OemId[4] = 'L';
}
STATIC
VOID
IScsiInitControlSection (
IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
IN UINTN HandleCount
)
/*++
Routine Description:
Initialize the control section of the iSCSI Boot Firmware Table.
Arguments:
Table - The ACPI table.
HandleCount - The number of the handles associated with iSCSI sessions, it's
equal to the number of iSCSI sessions.
Returns:
None.
--*/
{
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
UINTN NumOffset;
Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
NetZeroMem (Control, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE));
Control->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_ID;
Control->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE_VERSION;
Control->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE);
//
// Each session occupies two offsets, one for the NIC section,
// the other for the Target section.
//
NumOffset = 2 * HandleCount;
if (NumOffset > 4) {
//
// Need expand the control section if more than 2 NIC/Target sections
// exist.
//
Control->Header.Length += (UINT16) (NumOffset - 4) * sizeof (UINT16);
}
}
STATIC
VOID
IScsiAddHeapItem (
IN OUT UINT8 **Heap,
IN VOID *Data,
IN UINTN Len
)
/*++
Routine Description:
Add one item into the heap.
Arguments:
Heap - On input, the current address of the heap; On output, the address of
the heap after the item is added.
Data - The data to add into the heap.
Len - Length of the Data in byte.
Returns:
None.
--*/
{
//
// Add one byte for the NULL delimiter.
//
*Heap -= Len + 1;
NetCopyMem (*Heap, Data, Len);
*(*Heap + Len) = 0;
}
STATIC
VOID
IScsiFillInitiatorSection (
IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
IN OUT UINT8 **Heap,
IN EFI_HANDLE Handle
)
/*++
Routine Description:
Fill the Initiator section of the iSCSI Boot Firmware Table.
Arguments:
Table - The ACPI table.
Heap - The heap.
Handle - The handle associated with the iSCSI session.
Returns:
None.
--*/
{
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *Initiator;
ISCSI_DRIVER_DATA *DriverData;
ISCSI_SESSION *Session;
ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
EFI_STATUS Status;
Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
//
// Initiator section immediately follows the control section.
//
Initiator = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE *) ((UINT8 *) Control + IBFT_ROUNDUP (Control->Header.Length));
Control->InitiatorOffset = (UINT16) ((UINTN) Initiator - (UINTN) Table);
NetZeroMem (Initiator, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE));
Initiator->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_ID;
Initiator->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_VERSION;
Initiator->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE);
Initiator->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE_FLAG_BOOT_SELECTED;
//
// Get the identifier from the handle.
//
Status = gBS->HandleProtocol (Handle, &mIScsiPrivateGuid, &IScsiIdentifier);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return ;
}
DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
Session = &DriverData->Session;
//
// Fill the iSCSI Initiator Name into the heap.
//
IScsiAddHeapItem (Heap, Session->InitiatorName, Session->InitiatorNameLength - 1);
Initiator->IScsiNameLength = (UINT16) (Session->InitiatorNameLength - 1);
Initiator->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
}
STATIC
VOID
IScsiMapV4ToV6Addr (
IN EFI_IPv4_ADDRESS *V4,
OUT EFI_IPv6_ADDRESS *V6
)
/*++
Routine Description:
Map the v4 IP address into v6 IP address.
Arguments:
V4 - The v4 IP address.
V6 - The v6 IP address.
Returns:
None.
--*/
{
UINTN Index;
NetZeroMem (V6, sizeof (EFI_IPv6_ADDRESS));
V6->Addr[10] = 0xff;
V6->Addr[11] = 0xff;
for (Index = 0; Index < 4; Index++) {
V6->Addr[12 + Index] = V4->Addr[Index];
}
}
STATIC
UINT16
IScsiGetNICPciLocation (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
Get the NIC's PCI location and return it accroding to the composited
format defined in iSCSI Boot Firmware Table.
Arguments:
Controller - The handle of the controller.
Returns:
UINT16 - The composited representation of the NIC PCI location.
--*/
{
EFI_STATUS Status;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_HANDLE PciIoHandle;
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN Segment;
UINTN Bus;
UINTN Device;
UINTN Function;
Status = gBS->HandleProtocol (
Controller,
&gEfiDevicePathProtocolGuid,
&DevicePath
);
if (EFI_ERROR (Status)) {
return 0;
}
Status = gBS->LocateDevicePath (
&gEfiPciIoProtocolGuid,
&DevicePath,
&PciIoHandle
);
if (EFI_ERROR (Status)) {
return 0;
}
Status = gBS->HandleProtocol (PciIoHandle, &gEfiPciIoProtocolGuid, &PciIo);
if (EFI_ERROR (Status)) {
return 0;
}
Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
if (EFI_ERROR (Status)) {
return 0;
}
return (UINT16) ((Bus << 8) | (Device << 3) | Function);
}
STATIC
EFI_MAC_ADDRESS *
IScsiGetMacAddress (
IN EFI_HANDLE Controller
)
/*++
Routine Description:
Get the MAC address of the controller.
Arguments:
Controller - The handle of the controller.
Returns:
EFI_MAC_ADDRESS * - The mac address.
--*/
{
EFI_STATUS Status;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
Status = gBS->HandleProtocol (
Controller,
&gEfiSimpleNetworkProtocolGuid,
&Snp
);
ASSERT_EFI_ERROR (Status);
return &Snp->Mode->PermanentAddress;
}
STATIC
VOID
IScsiFillNICAndTargetSections (
IN EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table,
IN OUT UINT8 **Heap,
IN UINTN HandleCount,
IN EFI_HANDLE *Handles
)
/*++
Routine Description:
Fill the NIC and target sections in iSCSI Boot Firmware Table.
Arguments:
Table - The buffer of the ACPI table.
Heap - The heap buffer used to store the variable length parameters such as iSCSI name.
HandleCount - The number of handles having iSCSI private protocol installed.
Handles - The handle buffer.
Returns:
None.
--*/
{
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *Control;
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *Nic;
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *Target;
ISCSI_DRIVER_DATA *DriverData;
ISCSI_SESSION_CONFIG_DATA *SessionConfigData;
ISCSI_CHAP_AUTH_CONFIG_NVDATA *AuthConfig;
UINT16 *SectionOffset;
UINTN Index;
UINT16 Length;
EFI_MAC_ADDRESS *Mac;
ISCSI_PRIVATE_PROTOCOL *IScsiIdentifier;
EFI_STATUS Status;
//
// Get the offset of the first Nic and Target section.
//
Control = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_CONTROL_STRUCTURE *) (Table + 1);
Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Table +
Control->InitiatorOffset + IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_INITIATOR_STRUCTURE)));
Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
SectionOffset = &Control->NIC0Offset;
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (Handles[Index], &mIScsiPrivateGuid, &IScsiIdentifier);
if (EFI_ERROR (Status)) {
ASSERT (FALSE);
return ;
}
DriverData = ISCSI_DRIVER_DATA_FROM_IDENTIFIER (IScsiIdentifier);
SessionConfigData = &DriverData->Session.ConfigData;
AuthConfig = &DriverData->Session.AuthData.AuthConfig;
//
// Fill the Nic section.
//
NetZeroMem (Nic, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE));
Nic->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_ID;
Nic->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_VERSION;
Nic->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE);
Nic->Header.Index = (UINT8) Index;
Nic->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BLOCK_VALID |
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_BOOT_SELECTED |
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE_FLAG_GLOBAL;
//
// Get the subnet mask prefix length.
//
Nic->SubnetMaskPrefixLength = IScsiGetSubnetMaskPrefixLength (&SessionConfigData->NvData.SubnetMask);
if (SessionConfigData->NvData.InitiatorInfoFromDhcp) {
Nic->Origin = IpPrefixOriginDhcp;
} else {
Nic->Origin = IpPrefixOriginManual;
}
//
// Map the various v4 addresses into v6 addresses.
//
IScsiMapV4ToV6Addr (&SessionConfigData->NvData.LocalIp, &Nic->Ip);
IScsiMapV4ToV6Addr (&SessionConfigData->NvData.Gateway, &Nic->Gateway);
IScsiMapV4ToV6Addr (&SessionConfigData->PrimaryDns, &Nic->PrimaryDns);
IScsiMapV4ToV6Addr (&SessionConfigData->SecondaryDns, &Nic->SecondaryDns);
IScsiMapV4ToV6Addr (&SessionConfigData->DhcpServer, &Nic->DhcpServer);
Mac = IScsiGetMacAddress (DriverData->Controller);
NetCopyMem (Nic->Mac, Mac, sizeof (Nic->Mac));
//
// Get the PCI location of the Nic.
//
Nic->PciLocation = IScsiGetNICPciLocation (DriverData->Controller);
*SectionOffset = (UINT16) ((UINTN) Nic - (UINTN) Table);
SectionOffset++;
//
// Fill the Target section.
//
NetZeroMem (Target, sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE));
Target->Header.StructureId = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_ID;
Target->Header.Version = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_VERSION;
Target->Header.Length = sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE);
Target->Header.Index = (UINT8) Index;
Target->Header.Flags = EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BLOCK_VALID | EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE_FLAG_BOOT_SELECTED;
Target->Port = SessionConfigData->NvData.TargetPort;
Target->CHAPType = AuthConfig->CHAPType;
Target->NicIndex = (UINT8) Index;
IScsiMapV4ToV6Addr (&SessionConfigData->NvData.TargetIp, &Target->Ip);
NetCopyMem (Target->BootLun, SessionConfigData->NvData.BootLun, sizeof (Target->BootLun));
//
// Target iSCSI Name, CHAP name/secret, reverse CHAP name/secret.
//
Length = (UINT16) AsciiStrLen (SessionConfigData->NvData.TargetName);
IScsiAddHeapItem (Heap, SessionConfigData->NvData.TargetName, Length);
Target->IScsiNameLength = Length;
Target->IScsiNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
if (Target->CHAPType != ISCSI_CHAP_NONE) {
//
// CHAP Name
//
Length = (UINT16) AsciiStrLen (AuthConfig->CHAPName);
IScsiAddHeapItem (Heap, AuthConfig->CHAPName, Length);
Target->CHAPNameLength = Length;
Target->CHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
//
// CHAP Secret
//
Length = (UINT16) AsciiStrLen (AuthConfig->CHAPSecret);
IScsiAddHeapItem (Heap, AuthConfig->CHAPSecret, Length);
Target->CHAPSecretLength = Length;
Target->CHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
if (Target->CHAPType == ISCSI_CHAP_MUTUAL) {
//
// Reverse CHAP Name
//
Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPName);
IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPName, Length);
Target->ReverseCHAPNameLength = Length;
Target->ReverseCHAPNameOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
//
// Reverse CHAP Secret
//
Length = (UINT16) AsciiStrLen (AuthConfig->ReverseCHAPSecret);
IScsiAddHeapItem (Heap, AuthConfig->ReverseCHAPSecret, Length);
Target->ReverseCHAPSecretLength = Length;
Target->ReverseCHAPSecretOffset = (UINT16) ((UINTN) *Heap - (UINTN) Table);
}
}
*SectionOffset = (UINT16) ((UINTN) Target - (UINTN) Table);
SectionOffset++;
//
// Advance to the next NIC/Target pair
//
Nic = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE *) ((UINTN) Target +
IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE)));
Target = (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_TARGET_STRUCTURE *) ((UINTN) Nic +
IBFT_ROUNDUP (sizeof (EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_NIC_STRUCTURE)));
}
}
VOID
IScsiPublishIbft (
IN VOID
)
/*++
Routine Description:
Publish and remove the iSCSI Boot Firmware Table according to the iSCSI
session status.
Arguments:
None.
Returns:
None.
--*/
{
EFI_STATUS Status;
UINTN TableHandle;
EFI_ACPI_SUPPORT_PROTOCOL *AcpiSupport;
EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_HEADER *Table;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
UINT8 *Heap;
INTN Index;
EFI_ACPI_TABLE_VERSION Version;
UINT32 Signature;
Status = gBS->LocateProtocol (&gEfiAcpiSupportProtocolGuid, NULL, &AcpiSupport);
if (EFI_ERROR (Status)) {
return ;
}
//
// Try to remove the old iSCSI Boot Firmware Table.
//
for (Index = 0;; Index++) {
Status = AcpiSupport->GetAcpiTable (
AcpiSupport,
Index,
&Table,
&Version,
&TableHandle
);
if (EFI_ERROR (Status)) {
break;
}
Signature = Table->Signature;
NetFreePool (Table);
if (Signature == EFI_ACPI_3_0_ISCSI_BOOT_FIRMWARE_TABLE_SIGNATURE) {
//
// Remove the table.
//
Status = AcpiSupport->SetAcpiTable (
AcpiSupport,
NULL,
FALSE,
Version,
&TableHandle
);
if (EFI_ERROR (Status)) {
return ;
}
break;
}
}
//
// Get all iSCSI private protocols.
//
Status = gBS->LocateHandleBuffer (
ByProtocol,
&mIScsiPrivateGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return ;
}
//
// Allocate 4k bytes to hold the ACPI table.
//
Table = NetAllocatePool (IBFT_MAX_SIZE);
if (Table == NULL) {
return ;
}
Heap = (CHAR8 *) Table + IBFT_HEAP_OFFSET;
//
// Fill in the various section of the iSCSI Boot Firmware Table.
//
IScsiInitIbfTableHeader (Table);
IScsiInitControlSection (Table, HandleCount);
IScsiFillInitiatorSection (Table, &Heap, HandleBuffer[0]);
IScsiFillNICAndTargetSections (Table, &Heap, HandleCount, HandleBuffer);
NetFreePool (HandleBuffer);
TableHandle = 0;
//
// Install or update the iBFT table.
//
Status = AcpiSupport->SetAcpiTable (
AcpiSupport,
Table,
TRUE,
EFI_ACPI_TABLE_VERSION_3_0,
&TableHandle
);
if (!EFI_ERROR (Status)) {
AcpiSupport->PublishTables (AcpiSupport, EFI_ACPI_TABLE_VERSION_3_0);
}
NetFreePool (Table);
}

View File

@ -0,0 +1,40 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiIbft.h
Abstract:
Some extra definitions for iBFT.
--*/
#ifndef _ISCSI_IBFT_H_
#define _ISCSI_IBFT_H_
#include <industrystandard/IScsiBootFirmwareTable.h>
#include <protocol/AcpiSupport.h>
#include <protocol/PciIo.h>
#define IBFT_TABLE_VAR_NAME L"iBFT"
#define IBFT_MAX_SIZE 4096
#define IBFT_HEAP_OFFSET 2048
#define IBFT_ROUNDUP(size) NET_ROUNDUP ((size), EFI_ACPI_ISCSI_BOOT_FIRMWARE_TABLE_STRUCTURE_ALIGNMENT)
VOID
IScsiPublishIbft (
IN VOID
);
#endif

View File

@ -0,0 +1,161 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiImpl.h
Abstract:
--*/
#ifndef _ISCSI_IMPL_H_
#define _ISCSI_IMPL_H_
#include <Library/NetLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include "IScsiCommon.h"
#include "IScsiDriver.h"
#include "IScsiConfigNVDataStruc.h"
#include "IScsiExtScsiPassThru.h"
#include "IScsiProto.h"
#include "IScsiCHAP.h"
#include "IScsiDhcp.h"
#include "IScsiTcp4Io.h"
#include "IScsiIbft.h"
#include "IScsiMisc.h"
#include "IScsiConfig.h"
#define ISCSI_SESSION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'S', 'N')
typedef struct _ISCSI_SESSION {
UINT32 Signature;
ISCSI_SESSION_CONFIG_DATA ConfigData;
ISCSI_CHAP_AUTH_DATA AuthData;
CHAR8 InitiatorName[ISCSI_NAME_MAX_SIZE];
UINTN InitiatorNameLength;
UINT8 State;
UINT8 ISID[6];
UINT16 TSIH;
UINT32 CmdSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 InitiatorTaskTag;
UINT16 NextCID;
NET_LIST_ENTRY Conns;
UINT32 NumConns;
NET_LIST_ENTRY TcbList;
//
// session-wide parameters
//
UINT16 TargetPortalGroupTag;
UINT32 MaxConnections;
BOOLEAN InitialR2T;
BOOLEAN ImmediateData;
UINT32 MaxBurstLength;
UINT32 FirstBurstLength;
UINT32 DefaultTime2Wait;
UINT32 DefaultTime2Retain;
UINT16 MaxOutstandingR2T;
BOOLEAN DataPDUInOrder;
BOOLEAN DataSequenceInOrder;
UINT8 ErrorRecoveryLevel;
} ISCSI_SESSION;
#define ISCSI_CONNECTION_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'C', 'N')
typedef struct _ISCSI_CONNECTION {
UINT32 Signature;
NET_LIST_ENTRY Link;
EFI_EVENT TimeoutEvent;
ISCSI_SESSION *Session;
UINT8 State;
UINT8 CurrentStage;
UINT8 NextStage;
UINT8 CHAPStep;
BOOLEAN PartialReqSent;
BOOLEAN PartialRspRcvd;
BOOLEAN TransitInitiated;
UINT16 CID;
UINT32 ExpStatSN;
//
// queues...
//
NET_BUF_QUEUE RspQue;
TCP4_IO Tcp4Io;
//
// connection-only parameters
//
UINT32 MaxRecvDataSegmentLength;
ISCSI_DIGEST_TYPE HeaderDigest;
ISCSI_DIGEST_TYPE DataDigest;
} ISCSI_CONNECTION;
#define ISCSI_DRIVER_DATA_SIGNATURE EFI_SIGNATURE_32 ('I', 'S', 'D', 'A')
#define ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU(PassThru) \
CR ( \
PassThru, \
ISCSI_DRIVER_DATA, \
IScsiExtScsiPassThru, \
ISCSI_DRIVER_DATA_SIGNATURE \
)
#define ISCSI_DRIVER_DATA_FROM_IDENTIFIER(Identifier) \
CR ( \
Identifier, \
ISCSI_DRIVER_DATA, \
IScsiIdentifier, \
ISCSI_DRIVER_DATA_SIGNATURE \
)
#define ISCSI_DRIVER_DATA_FROM_SESSION(s) \
CR ( \
s, \
ISCSI_DRIVER_DATA, \
Session, \
ISCSI_DRIVER_DATA_SIGNATURE \
)
typedef struct _ISCSI_DRIVER_DATA {
UINT32 Signature;
EFI_HANDLE Image;
EFI_HANDLE Controller;
ISCSI_PRIVATE_PROTOCOL IScsiIdentifier;
EFI_EVENT ExitBootServiceEvent;
EFI_EXT_SCSI_PASS_THRU_PROTOCOL IScsiExtScsiPassThru;
EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;
EFI_HANDLE ExtScsiPassThruHandle;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
ISCSI_SESSION Session;
} ISCSI_DRIVER_DATA;
#endif

View File

@ -0,0 +1,145 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiInitiatorName.c
Abstract:
Implementation for EFI iSCSI Initiator Name Protocol.
--*/
#include "IScsiImpl.h"
EFI_ISCSI_INITIATOR_NAME_PROTOCOL gIScsiInitiatorName = {
IScsiGetInitiatorName,
IScsiSetInitiatorName
};
EFI_STATUS
EFIAPI
IScsiGetInitiatorName (
IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Retrieves the current set value of iSCSI Initiator Name.
Arguments:
This - Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance.
BufferSize - Size of the buffer in bytes pointed to by Buffer / Actual size of
the variable data buffer.
Buffer - Pointer to the buffer for data to be read.
Returns:
EFI_SUCCESS - Data was successfully retrieved into the provided
buffer and the BufferSize was sufficient to handle the
iSCSI initiator name.
EFI_BUFFER_TOO_SMALL - BufferSize is too small for the result. BufferSize will
be updated with the size required to complete the request.
Buffer will not be affected.
EFI_INVALID_PARAMETER - BufferSize is NULL. BufferSize and Buffer will not be
affected.
EFI_INVALID_PARAMETER - Buffer is NULL. BufferSize and Buffer will not be
affected.
EFI_DEVICE_ERROR - The iSCSI initiator name could not be retrieved due to
a hardware error.
--*/
{
EFI_STATUS Status;
if ((BufferSize == NULL) || (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
Status = gRT->GetVariable (
ISCSI_INITIATOR_NAME_VAR_NAME,
&gEfiIScsiInitiatorNameProtocolGuid,
NULL,
BufferSize,
Buffer
);
return Status;
}
EFI_STATUS
EFIAPI
IScsiSetInitiatorName (
IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This,
IN OUT UINTN *BufferSize,
OUT VOID *Buffer
)
/*++
Routine Description:
Sets the iSSI Initiator Name.
Arguments:
This - Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance.
BufferSize - Size of the buffer in bytes pointed to by Buffer.
Buffer - Pointer to the buffer for data to be written.
Returns:
EFI_SUCCESS - Data was successfully stored by the protocol.
EFI_UNSUPPORTED - Platform policies do not allow for data to be written.
EFI_INVALID_PARAMETER - BufferSize exceeds the maximum allowed limit.
BufferSize will be updated with the maximum size
required to complete the request.
EFI_INVALID_PARAMETER - Buffersize is NULL. BufferSize and Buffer will not be
affected.
EFI_INVALID_PARAMETER - Buffer is NULL. BufferSize and Buffer will not be affected.
EFI_DEVICE_ERROR - The data could not be stored due to a hardware error.
EFI_OUT_OF_RESOURCES - Not enough storage is available to hold the data
EFI_PROTOCOL_ERROR - Input iSCSI initiator name does not adhere to RFC 3720
--*/
{
EFI_STATUS Status;
if ((BufferSize == NULL) || (Buffer == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (*BufferSize > ISCSI_NAME_MAX_SIZE) {
*BufferSize = ISCSI_NAME_MAX_SIZE;
return EFI_INVALID_PARAMETER;
}
//
// only support iqn iSCSI names.
//
Status = IScsiNormalizeName ((CHAR8 *) Buffer, *BufferSize - 1);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gRT->SetVariable (
ISCSI_INITIATOR_NAME_VAR_NAME,
&gEfiIScsiInitiatorNameProtocolGuid,
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
*BufferSize,
Buffer
);
return Status;
}

View File

@ -0,0 +1,965 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiMisc.c
Abstract:
Miscellaneous routines for iSCSI driver.
--*/
#include "IScsiImpl.h"
STATIC CONST CHAR8 IScsiHexString[] = "0123456789ABCDEFabcdef";
static
BOOLEAN
IsHexDigit (
OUT UINT8 *Digit,
IN CHAR16 Char
)
/*++
Routine Description:
Determines if a Unicode character is a hexadecimal digit.
The test is case insensitive.
Arguments:
Digit - Pointer to byte that receives the value of the hex character.
Char - Unicode character to test.
Returns:
TRUE - If the character is a hexadecimal digit.
FALSE - Otherwise.
--*/
{
if ((Char >= L'0') && (Char <= L'9')) {
*Digit = (UINT8) (Char - L'0');
return TRUE;
}
if ((Char >= L'A') && (Char <= L'F')) {
*Digit = (UINT8) (Char - L'A' + 0x0A);
return TRUE;
}
if ((Char >= L'a') && (Char <= L'f')) {
*Digit = (UINT8) (Char - L'a' + 0x0A);
return TRUE;
}
return FALSE;
}
static
VOID
StrTrim (
IN OUT CHAR16 *str,
IN CHAR16 CharC
)
/*++
Routine Description:
Removes (trims) specified leading and trailing characters from a string.
Arguments:
str - Pointer to the null-terminated string to be trimmed. On return,
str will hold the trimmed string.
CharC - Character will be trimmed from str.
Returns:
--*/
{
CHAR16 *p1;
CHAR16 *p2;
if (*str == 0) {
return;
}
//
// Trim off the leading and trailing characters c
//
for (p1 = str; *p1 && *p1 == CharC; p1++) {
;
}
p2 = str;
if (p2 == p1) {
while (*p1) {
p2++;
p1++;
}
} else {
while (*p1) {
*p2 = *p1;
p1++;
p2++;
}
*p2 = 0;
}
for (p1 = str + StrLen(str) - 1; p1 >= str && *p1 == CharC; p1--) {
;
}
if (p1 != str + StrLen(str) - 1) {
*(p1 + 1) = 0;
}
}
UINT8
IScsiGetSubnetMaskPrefixLength (
IN EFI_IPv4_ADDRESS *SubnetMask
)
/*++
Routine Description:
Calculate the prefix length of the IPv4 subnet mask.
Arguments:
SubnetMask - The IPv4 subnet mask.
Returns:
The prefix length of the subnet mask.
--*/
{
UINT8 Len;
UINT32 ReverseMask;
//
// The SubnetMask is in network byte order.
//
ReverseMask = (SubnetMask->Addr[0] << 24) | (SubnetMask->Addr[1] << 16) | (SubnetMask->Addr[2] << 8) | (SubnetMask->Addr[3]);
//
// Reverse it.
//
ReverseMask = ~ReverseMask;
if (ReverseMask & (ReverseMask + 1)) {
return 0;
}
Len = 0;
while (ReverseMask != 0) {
ReverseMask = ReverseMask >> 1;
Len++;
}
return 32 - Len;
}
EFI_STATUS
IScsiAsciiStrToLun (
IN CHAR8 *Str,
OUT UINT8 *Lun
)
/*++
Routine Description:
Convert the hexadecimal encoded LUN string into the 64-bit LUN.
Arguments:
Str - The hexadecimal encoded LUN string.
Lun - Storage to return the 64-bit LUN.
Returns:
EFI_SUCCESS - The 64-bit LUN is stored in Lun.
EFI_INVALID_PARAMETER - The string is malformatted.
--*/
{
UINT32 Index;
CHAR8 *LunUnitStr[4];
CHAR8 Digit;
NetZeroMem (Lun, 8);
NetZeroMem (LunUnitStr, sizeof (LunUnitStr));
Index = 0;
LunUnitStr[0] = Str;
if (!IsHexDigit (&Digit, *Str)) {
return EFI_INVALID_PARAMETER;
}
while (*Str != '\0') {
//
// Legal representations of LUN:
// 4752-3A4F-6b7e-2F99,
// 6734-9-156f-127,
// 4186-9
//
if (*Str == '-') {
*Str = '\0';
Index++;
if (*(Str + 1) != '\0') {
if (!IsHexDigit (&Digit, *(Str + 1))) {
return EFI_INVALID_PARAMETER;
}
LunUnitStr[Index] = Str + 1;
}
} else if (!IsHexDigit (&Digit, *Str)) {
return EFI_INVALID_PARAMETER;
}
Str++;
}
for (Index = 0; (Index < 4) && (LunUnitStr[Index] != NULL); Index++) {
if (AsciiStrLen (LunUnitStr[Index]) > 4) {
return EFI_INVALID_PARAMETER;
}
*((UINT16 *) &Lun[Index * 2]) = HTONS (AsciiStrHexToUintn (LunUnitStr[Index]));
}
return EFI_SUCCESS;
}
VOID
IScsiLunToUnicodeStr (
IN UINT8 *Lun,
OUT CHAR16 *Str
)
/*++
Routine Description:
Convert the 64-bit LUN into the hexadecimal encoded LUN string.
Arguments:
Lun - The 64-bit LUN.
Str - The storage to return the hexadecimal encoded LUN string.
Returns:
None.
--*/
{
UINTN Index;
CHAR16 *TempStr;
TempStr = Str;
for (Index = 0; Index < 4; Index++) {
if ((Lun[2 * Index] | Lun[2 * Index + 1]) == 0) {
StrCpy (TempStr, L"0-");
} else {
TempStr[0] = (CHAR16) IScsiHexString[Lun[2 * Index] >> 4];
TempStr[1] = (CHAR16) IScsiHexString[Lun[2 * Index] & 0xf];
TempStr[2] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] >> 4];
TempStr[3] = (CHAR16) IScsiHexString[Lun[2 * Index + 1] & 0xf];
TempStr[4] = L'-';
TempStr[5] = 0;
StrTrim (TempStr, L'0');
}
TempStr += StrLen (TempStr);
}
Str[StrLen (Str) - 1] = 0;
for (Index = StrLen (Str) - 1; Index > 1; Index = Index - 2) {
if ((Str[Index] == L'0') && (Str[Index - 1] == L'-')) {
Str[Index - 1] = 0;
} else {
break;
}
}
}
CHAR16 *
IScsiAsciiStrToUnicodeStr (
IN CHAR8 *Source,
OUT CHAR16 *Destination
)
/*++
Routine Description:
Convert the ASCII string into a UNICODE string.
Arguments:
Source - The ASCII string.
Destination - The storage to return the UNICODE string.
Returns:
Pointer to the UNICODE string.
--*/
{
ASSERT (Destination != NULL);
ASSERT (Source != NULL);
while (*Source != '\0') {
*(Destination++) = (CHAR16) *(Source++);
}
*Destination = '\0';
return Destination;
}
CHAR8 *
IScsiUnicodeStrToAsciiStr (
IN CHAR16 *Source,
OUT CHAR8 *Destination
)
/*++
Routine Description:
Convert the UNICODE string into an ASCII string.
Arguments:
Source - The UNICODE string.
Destination - The storage to return the ASCII string.
Returns:
Pointer to the ASCII string.
--*/
{
ASSERT (Destination != NULL);
ASSERT (Source != NULL);
while (*Source != '\0') {
//
// If any Unicode characters in Source contain
// non-zero value in the upper 8 bits, then ASSERT().
//
ASSERT (*Source < 0x100);
*(Destination++) = (CHAR8) *(Source++);
}
*Destination = '\0';
return Destination;
}
EFI_STATUS
IScsiAsciiStrToIp (
IN CHAR8 *Str,
OUT EFI_IPv4_ADDRESS *Ip
)
/*++
Routine Description:
Convert the decimal dotted IPv4 address into the binary IPv4 address.
Arguments:
Str - The UNICODE string.
Ip - The storage to return the ASCII string.
Returns:
EFI_SUCCESS - The binary IP address is returned in Ip.
EFI_INVALID_PARAMETER - The IP string is malformatted.
--*/
{
UINTN Index;
UINTN Number;
Index = 0;
while (*Str) {
if (Index > 3) {
return EFI_INVALID_PARAMETER;
}
Number = 0;
while (NET_IS_DIGIT (*Str)) {
Number = Number * 10 + (*Str - '0');
Str++;
}
if (Number > 0xFF) {
return EFI_INVALID_PARAMETER;
}
Ip->Addr[Index] = (UINT8) Number;
if ((*Str != '\0') && (*Str != '.')) {
//
// The current character should be either the NULL terminator or
// the dot delimiter.
//
return EFI_INVALID_PARAMETER;
}
if (*Str == '.') {
//
// Skip the delimiter.
//
Str++;
}
Index++;
}
if (Index != 4) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
VOID
IScsiMacAddrToStr (
IN EFI_MAC_ADDRESS *Mac,
IN UINT32 Len,
OUT CHAR16 *Str
)
/*++
Routine Description:
Convert the mac address into a hexadecimal encoded "-" seperated string.
Arguments:
Mac - The mac address.
Len - Length in bytes of the mac address.
Str - The storage to return the mac string.
Returns:
None.
--*/
{
UINT32 Index;
for (Index = 0; Index < Len; Index++) {
Str[3 * Index] = NibbleToHexChar (Mac->Addr[Index] >> 4);
Str[3 * Index + 1] = NibbleToHexChar (Mac->Addr[Index]);
Str[3 * Index + 2] = L'-';
}
Str[3 * Index - 1] = L'\0';
}
EFI_STATUS
IScsiBinToHex (
IN UINT8 *BinBuffer,
IN UINT32 BinLength,
IN OUT CHAR8 *HexStr,
IN OUT UINT32 *HexLength
)
/*++
Routine Description:
Convert the binary encoded buffer into a hexadecimal encoded string.
Arguments:
BinBuffer - The buffer containing the binary data.
BinLength - Length of the binary buffer.
HexStr - Pointer to the string.
HexLength - The length of the string.
Returns:
EFI_SUCCESS - The binary data is converted to the hexadecimal string
and the length of the string is updated.
EFI_BUFFER_TOO_SMALL - The string is too small.
--*/
{
UINTN Index;
if ((HexStr == NULL) || (BinBuffer == NULL) || (BinLength == 0)) {
return EFI_INVALID_PARAMETER;
}
if (((*HexLength) - 3) < BinLength * 2) {
*HexLength = BinLength * 2 + 3;
return EFI_BUFFER_TOO_SMALL;
}
*HexLength = BinLength * 2 + 3;
//
// Prefix for Hex String
//
HexStr[0] = '0';
HexStr[1] = 'x';
for (Index = 0; Index < BinLength; Index++) {
HexStr[Index * 2 + 2] = IScsiHexString[BinBuffer[Index] >> 4];
HexStr[Index * 2 + 3] = IScsiHexString[BinBuffer[Index] & 0xf];
}
HexStr[Index * 2 + 2] = '\0';
return EFI_SUCCESS;
}
EFI_STATUS
IScsiHexToBin (
IN OUT UINT8 *BinBuffer,
IN OUT UINT32 *BinLength,
IN CHAR8 *HexStr
)
/*++
Routine Description:
Convert the hexadecimal string into a binary encoded buffer.
Arguments:
BinBuffer - The binary buffer.
BinLength - Length of the binary buffer.
HexStr - The hexadecimal string.
Returns:
EFI_SUCCESS - The hexadecimal string is converted into a binary
encoded buffer.
EFI_BUFFER_TOO_SMALL - The binary buffer is too small to hold the converted data.s
--*/
{
UINTN Index;
UINT32 HexCount;
CHAR8 *HexBuf;
UINT8 Digit;
UINT8 Byte;
//
// Find out how many hex characters the string has.
//
HexBuf = HexStr;
if ((HexBuf[0] == '0') && ((HexBuf[1] == 'x') || (HexBuf[1] == 'X'))) {
HexBuf += 2;
}
for (Index = 0, HexCount = 0; IsHexDigit (&Digit, HexBuf[Index]); Index++, HexCount++)
;
if (HexCount == 0) {
*BinLength = 0;
return EFI_SUCCESS;
}
//
// Test if buffer is passed enough.
//
if (((HexCount + 1) / 2) > *BinLength) {
*BinLength = (HexCount + 1) / 2;
return EFI_BUFFER_TOO_SMALL;
}
*BinLength = (HexCount + 1) / 2;
for (Index = 0; Index < HexCount; Index++) {
IsHexDigit (&Digit, HexBuf[HexCount - 1 - Index]);
if ((Index & 1) == 0) {
Byte = Digit;
} else {
Byte = BinBuffer[*BinLength - 1 - Index / 2];
Byte &= 0x0F;
Byte |= Digit << 4;
}
BinBuffer[*BinLength - 1 - Index / 2] = Byte;
}
return EFI_SUCCESS;
}
VOID
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
)
/*++
Routine Description:
Generate random numbers.
Arguments:
Rand - The buffer to contain random numbers.
RandLength - The length of the Rand buffer.
Returns:
None.
--*/
{
UINT32 Random;
while (RandLength > 0) {
Random = NET_RANDOM (NetRandomInitSeed ());
*Rand++ = (UINT8) (Random);
RandLength--;
}
}
ISCSI_DRIVER_DATA *
IScsiCreateDriverData (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller
)
/*++
Routine Description:
Create the iSCSI driver data..
Arguments:
Image - The handle of the driver image.
Controller - The handle of the controller.
Returns:
The iSCSI driver data created.
--*/
{
ISCSI_DRIVER_DATA *Private;
EFI_STATUS Status;
Private = NetAllocateZeroPool (sizeof (ISCSI_DRIVER_DATA));
if (Private == NULL) {
return NULL;
}
Private->Signature = ISCSI_DRIVER_DATA_SIGNATURE;
Private->Image = Image;
Private->Controller = Controller;
//
// Create an event to be signal when the BS to RT transition is triggerd so
// as to abort the iSCSI session.
//
Status = gBS->CreateEvent (
EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
TPL_CALLBACK,
IScsiOnExitBootService,
Private,
&Private->ExitBootServiceEvent
);
if (EFI_ERROR (Status)) {
NetFreePool (Private);
return NULL;
}
NetCopyMem(&Private->IScsiExtScsiPassThru, &gIScsiExtScsiPassThruProtocolTemplate, sizeof(EFI_EXT_SCSI_PASS_THRU_PROTOCOL));
//
// 0 is designated to the TargetId, so use another value for the AdapterId.
//
Private->ExtScsiPassThruMode.AdapterId = 2;
Private->ExtScsiPassThruMode.Attributes = EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL;
Private->ExtScsiPassThruMode.IoAlign = 4;
Private->IScsiExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
//
// Install the Ext SCSI PASS THRU protocol.
//
Status = gBS->InstallProtocolInterface (
&Private->ExtScsiPassThruHandle,
&gEfiExtScsiPassThruProtocolGuid,
EFI_NATIVE_INTERFACE,
&Private->IScsiExtScsiPassThru
);
if (EFI_ERROR (Status)) {
gBS->CloseEvent (Private->ExitBootServiceEvent);
NetFreePool (Private);
return NULL;
}
IScsiSessionInit (&Private->Session, FALSE);
return Private;
}
VOID
IScsiCleanDriverData (
IN ISCSI_DRIVER_DATA *Private
)
/*++
Routine Description:
Clean the iSCSI driver data.
Arguments:
Private - The iSCSI driver data.
Returns:
None.
--*/
{
if (Private->DevicePath != NULL) {
gBS->UninstallProtocolInterface (
Private->ExtScsiPassThruHandle,
&gEfiDevicePathProtocolGuid,
Private->DevicePath
);
NetFreePool (Private->DevicePath);
}
if (Private->ExtScsiPassThruHandle != NULL) {
gBS->UninstallProtocolInterface (
Private->ExtScsiPassThruHandle,
&gEfiExtScsiPassThruProtocolGuid,
&Private->IScsiExtScsiPassThru
);
}
gBS->CloseEvent (Private->ExitBootServiceEvent);
NetFreePool (Private);
}
EFI_STATUS
IScsiGetConfigData (
IN ISCSI_DRIVER_DATA *Private
)
/*++
Routine Description:
Get the various configuration data of this iSCSI instance.
Arguments:
Private - The iSCSI driver data.
Returns:
EFI_SUCCESS - The configuration of this instance is got.
EFI_NOT_FOUND - This iSCSI instance is not configured yet.
--*/
{
EFI_STATUS Status;
ISCSI_SESSION *Session;
UINTN BufferSize;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_SIMPLE_NETWORK_MODE *Mode;
CHAR16 MacString[65];
//
// get the iSCSI Initiator Name
//
Session = &Private->Session;
Session->InitiatorNameLength = ISCSI_NAME_MAX_SIZE;
Status = gIScsiInitiatorName.Get (
&gIScsiInitiatorName,
&Session->InitiatorNameLength,
Session->InitiatorName
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->HandleProtocol (
Private->Controller,
&gEfiSimpleNetworkProtocolGuid,
&Snp
);
if (EFI_ERROR (Status)) {
return Status;
}
Mode = Snp->Mode;
//
// Get the mac string, it's the name of various variable
//
IScsiMacAddrToStr (&Mode->PermanentAddress, Mode->HwAddressSize, MacString);
//
// Get the normal configuration.
//
BufferSize = sizeof (Session->ConfigData.NvData);
Status = gRT->GetVariable (
MacString,
&gEfiIScsiInitiatorNameProtocolGuid,
NULL,
&BufferSize,
&Session->ConfigData.NvData
);
if (EFI_ERROR (Status)) {
return Status;
}
if (!Session->ConfigData.NvData.Enabled) {
return EFI_ABORTED;
}
//
// Get the CHAP Auth information.
//
BufferSize = sizeof (Session->AuthData.AuthConfig);
Status = gRT->GetVariable (
MacString,
&mIScsiCHAPAuthInfoGuid,
NULL,
&BufferSize,
&Session->AuthData.AuthConfig
);
if (!EFI_ERROR (Status) && Session->ConfigData.NvData.InitiatorInfoFromDhcp) {
//
// Start dhcp.
//
Status = IScsiDoDhcp (Private->Image, Private->Controller, &Session->ConfigData);
}
return Status;
}
EFI_DEVICE_PATH_PROTOCOL *
IScsiGetTcpConnDevicePath (
IN ISCSI_DRIVER_DATA *Private
)
/*++
Routine Description:
Get the device path of the iSCSI tcp connection and update it.
Arguments:
Private - The iSCSI driver data.
Returns:
The updated device path.
--*/
{
ISCSI_SESSION *Session;
ISCSI_CONNECTION *Conn;
TCP4_IO *Tcp4Io;
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
EFI_STATUS Status;
EFI_DEV_PATH *DPathNode;
Session = &Private->Session;
if (Session->State != SESSION_STATE_LOGGED_IN) {
return NULL;
}
Conn = NET_LIST_USER_STRUCT_S (
Session->Conns.ForwardLink,
ISCSI_CONNECTION,
Link,
ISCSI_CONNECTION_SIGNATURE
);
Tcp4Io = &Conn->Tcp4Io;
Status = gBS->HandleProtocol (
Tcp4Io->Handle,
&gEfiDevicePathProtocolGuid,
&DevicePath
);
if (EFI_ERROR (Status)) {
return NULL;
}
//
// Duplicate it.
//
DevicePath = DuplicateDevicePath (DevicePath);
DPathNode = (EFI_DEV_PATH *) DevicePath;
while (!IsDevicePathEnd (&DPathNode->DevPath)) {
if ((DevicePathType (&DPathNode->DevPath) == MESSAGING_DEVICE_PATH) &&
(DevicePathSubType (&DPathNode->DevPath) == MSG_IPv4_DP)
) {
DPathNode->Ipv4.LocalPort = 0;
DPathNode->Ipv4.StaticIpAddress = !Session->ConfigData.NvData.InitiatorInfoFromDhcp;
break;
}
DPathNode = (EFI_DEV_PATH *) NextDevicePathNode (&DPathNode->DevPath);
}
return DevicePath;
}
VOID
EFIAPI
IScsiOnExitBootService (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Abort the session when the transition from BS to RT is initiated.
Arguments:
Event - The event signaled.
Context - The iSCSI driver data.
Returns:
None.
--*/
{
ISCSI_DRIVER_DATA *Private;
Private = (ISCSI_DRIVER_DATA *) Context;
gBS->CloseEvent (Private->ExitBootServiceEvent);
IScsiSessionAbort (&Private->Session);
}

View File

@ -0,0 +1,143 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiMisc.h
Abstract:
Miscellaneous definitions for iSCSI driver.
--*/
#ifndef _ISCSI_MISC_H_
#define _ISCSI_MISC_H_
#pragma pack(1)
typedef struct _ISCSI_SESSION_CONFIG_NVDATA {
BOOLEAN Enabled;
BOOLEAN InitiatorInfoFromDhcp;
EFI_IPv4_ADDRESS LocalIp;
EFI_IPv4_ADDRESS SubnetMask;
EFI_IPv4_ADDRESS Gateway;
BOOLEAN TargetInfoFromDhcp;
CHAR8 TargetName[ISCSI_NAME_MAX_SIZE];
EFI_IPv4_ADDRESS TargetIp;
UINT16 TargetPort;
UINT8 BootLun[8];
} ISCSI_SESSION_CONFIG_NVDATA;
#pragma pack()
typedef struct _ISCSI_SESSION_CONFIG_DATA {
ISCSI_SESSION_CONFIG_NVDATA NvData;
EFI_IPv4_ADDRESS PrimaryDns;
EFI_IPv4_ADDRESS SecondaryDns;
EFI_IPv4_ADDRESS DhcpServer;
} ISCSI_SESSION_CONFIG_DATA;
UINT8
IScsiGetSubnetMaskPrefixLength (
IN EFI_IPv4_ADDRESS *SubnetMask
);
EFI_STATUS
IScsiAsciiStrToLun (
IN CHAR8 *Str,
OUT UINT8 *Lun
);
VOID
IScsiLunToUnicodeStr (
IN UINT8 *Lun,
OUT CHAR16 *String
);
CHAR16 *
IScsiAsciiStrToUnicodeStr (
IN CHAR8 *Source,
OUT CHAR16 *Destination
);
CHAR8 *
IScsiUnicodeStrToAsciiStr (
IN CHAR16 *Source,
OUT CHAR8 *Destination
);
VOID
IScsiMacAddrToStr (
IN EFI_MAC_ADDRESS *Mac,
IN UINT32 Len,
OUT CHAR16 *Str
);
EFI_STATUS
IScsiAsciiStrToIp (
IN CHAR8 *Str,
OUT EFI_IPv4_ADDRESS *Ip
);
EFI_STATUS
IScsiBinToHex (
IN UINT8 *BinBuffer,
IN UINT32 BinLength,
IN OUT CHAR8 *HexStr,
IN OUT UINT32 *HexLength
);
EFI_STATUS
IScsiHexToBin (
IN OUT UINT8 *BinBuffer,
IN OUT UINT32 *BinLength,
IN CHAR8 *HexStr
);
VOID
IScsiGenRandom (
IN OUT UINT8 *Rand,
IN UINTN RandLength
);
ISCSI_DRIVER_DATA *
IScsiCreateDriverData (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller
);
VOID
IScsiCleanDriverData (
IN ISCSI_DRIVER_DATA *Private
);
EFI_STATUS
IScsiGetConfigData (
IN ISCSI_DRIVER_DATA *Private
);
EFI_DEVICE_PATH_PROTOCOL *
IScsiGetTcpConnDevicePath (
IN ISCSI_DRIVER_DATA *Private
);
VOID
EFIAPI
IScsiOnExitBootService (
IN EFI_EVENT Event,
IN VOID *Context
);
extern CHAR16 NibbleToHexChar(UINT8 Nibble);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,786 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiProto.h
Abstract:
Protocol definitions for iSCSI driver, mainly from RFC3720.
--*/
#ifndef _ISCSI_PROTO_H_
#define _ISCSI_PROTO_H_
#include <protocol/ScsiPassThruExt.h>
//
// RFC 1982 Serial Number Arithmetic, SERIAL_BITS = 32
//
#define ISCSI_SEQ_EQ(s1, s2) ((s1) == (s2))
#define ISCSI_SEQ_LT(s1, s2) \
( \
(((INT32) (s1) < (INT32) (s2)) && (s2 - s1) < (1 << 31)) || \
(((INT32) (s1) > (INT32) (s2)) && (s1 - s2) > (1 << 31)) \
)
#define ISCSI_SEQ_GT(s1, s2) \
( \
(((INT32) (s1) < (INT32) (s2)) && (s2 - s1) > (1 << 31)) || \
(((INT32) (s1) > (INT32) (s2)) && (s1 - s2) < (1 << 31)) \
)
#define ISCSI_WELL_KNOWN_PORT 3260
#define ISCSI_MAX_CONNS_PER_SESSION 1
#define DEFAULT_MAX_RECV_DATA_SEG_LEN 8192
#define MAX_RECV_DATA_SEG_LEN_IN_FFP 65536
#define DEFAULT_MAX_OUTSTANDING_R2T 1
#define ISCSI_VERSION_MAX 0x00
#define ISCSI_VERSION_MIN 0x00
#define ISID_BYTE_0 0 // OUI format
#define ISID_BYTE_1 0
#define ISID_BYTE_2 0xaa
#define ISID_BYTE_3 0x1
#define ISCSI_KEY_AUTH_METHOD "AuthMethod"
#define ISCSI_KEY_HEADER_DIGEST "HeaderDigest"
#define ISCSI_KEY_DATA_DIGEST "DataDigest"
#define ISCSI_KEY_MAX_CONNECTIONS "MaxConnections"
#define ISCSI_KEY_TARGET_NAME "TargetName"
#define ISCSI_KEY_INITIATOR_NAME "InitiatorName"
#define ISCSI_KEY_TARGET_ALIAS "TargetAlias"
#define ISCSI_KEY_INITIATOR_ALIAS "InitiatorAlias"
#define ISCSI_KEY_TARGET_ADDRESS "TargetAddress"
#define ISCSI_KEY_INITIAL_R2T "InitialR2T"
#define ISCSI_KEY_IMMEDIATE_DATA "ImmediateData"
#define ISCSI_KEY_TARGET_PORTAL_GROUP_TAG "TargetPortalGroupTag"
#define ISCSI_KEY_MAX_BURST_LENGTH "MaxBurstLength"
#define ISCSI_KEY_FIRST_BURST_LENGTH "FirstBurstLength"
#define ISCSI_KEY_DEFAULT_TIME2WAIT "DefaultTime2Wait"
#define ISCSI_KEY_DEFAULT_TIME2RETAIN "DefaultTime2Retain"
#define ISCSI_KEY_MAX_OUTSTANDING_R2T "MaxOutstandingR2T"
#define ISCSI_KEY_DATA_PDU_IN_ORDER "DataPDUInOrder"
#define ISCSI_KEY_DATA_SEQUENCE_IN_ORDER "DataSequenceInOrder"
#define ISCSI_KEY_ERROR_RECOVERY_LEVEL "ErrorRecoveryLevel"
#define ISCSI_KEY_SESSION_TYPE "SessionType"
#define ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH "MaxRecvDataSegmentLength"
#define ISCSI_KEY_VALUE_NONE "None"
//
// connection state for initiator
//
typedef enum {
CONN_STATE_FREE,
CONN_STATE_XPT_WAIT,
CONN_STATE_IN_LOGIN,
CONN_STATE_LOGGED_IN,
CONN_STATE_IN_LOGOUT,
CONN_STATE_LOGOUT_REQUESTED,
CONN_STATE_CLEANUP_WAIT,
CONN_STATE_IN_CLEANUP
} CONNECTION_STATE;
//
// session state for initiator
//
typedef enum {
SESSION_STATE_FREE,
SESSION_STATE_LOGGED_IN,
SESSION_STATE_FAILED
} SESSION_STATE;
typedef enum {
DataIn = 0,
DataOut = 1,
DataBi = 2
} DATA_DIRECTION;
#define ISCSI_RESERVED_TAG 0xffffffff
#define ISCSI_REQ_IMMEDIATE 0x40
#define ISCSI_OPCODE_MASK 0x3F
#define ISCSI_SET_OPCODE(PduHdr, Op, Flgs) ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) = ((Op) | (Flgs)))
#define ISCSI_GET_OPCODE(PduHdr) ((((ISCSI_BASIC_HEADER *) (PduHdr))->OpCode) & ISCSI_OPCODE_MASK)
#define ISCSI_CHECK_OPCODE(PduHdr, Op) ((((PduHdr)->OpCode) & ISCSI_OPCODE_MASK) == (Op))
#define ISCSI_IMMEDIATE_ON(PduHdr) ((PduHdr)->OpCode & ISCSI_REQ_IMMEDIATE)
#define ISCSI_SET_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags |= (Flag))
#define ISCSI_CLEAR_FLAG(PduHdr, Flag) (((ISCSI_BASIC_HEADER *) (PduHdr))->Flags &= ~(Flag))
#define ISCSI_FLAG_ON(PduHdr, Flag) ((((ISCSI_BASIC_HEADER *) (PduHdr))->Flags & (Flag)) == (Flag))
#define ISCSI_SET_STAGES(PduHdr, Cur, Nxt) ((PduHdr)->Flags |= ((Cur) << 2 | (Nxt)))
#define ISCSI_GET_CURRENT_STAGE(PduHdr) (((PduHdr)->Flags >> 2) & 0x3)
#define ISCSI_GET_NEXT_STAGE(PduHdr) (((PduHdr)->Flags) & 0x3)
#define ISCSI_GET_PAD_LEN(DataLen) ((~(DataLen) + 1) & 0x3)
#define ISCSI_ROUNDUP(DataLen) (((DataLen) + 3) &~(0x3))
#define HTON24(Dst, Src) \
do { \
(Dst)[0] = (UINT8) ((Src) >> 16) & 0xFF; \
(Dst)[1] = (UINT8) ((Src) >> 8) & 0xFF; \
(Dst)[2] = (UINT8) (Src) & 0xFF; \
} while (0);
#define NTOH24(src) (((src)[0] << 16) | ((src)[1] << 8) | ((src)[2]))
#define ISCSI_GET_DATASEG_LEN(PduHdr) NTOH24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength)
#define ISCSI_SET_DATASEG_LEN(PduHdr, Len) HTON24 (((ISCSI_BASIC_HEADER *) (PduHdr))->DataSegmentLength, (Len))
//
// initiator opcodes
//
#define ISCSI_OPCODE_NOP_OUT 0x00
#define ISCSI_OPCODE_SCSI_CMD 0x01
#define ISCSI_OPCODE_SCSI_TMF_REQ 0x02
#define ISCSI_OPCODE_LOGIN_REQ 0x03
#define ISCSI_OPCODE_TEXT_REQ 0x04
#define ISCSI_OPCODE_SCSI_DATA_OUT 0x05
#define ISCSI_OPCODE_LOGOUT_REQ 0x06
#define ISCSI_OPCODE_SNACK_REQ 0x10
#define ISCSI_OPCODE_VENDOR_I0 0x1c
#define ISCSI_OPCODE_VENDOR_I1 0x1d
#define ISCSI_OPCODE_VENDOR_I2 0x1e
//
// target opcodes
//
#define ISCSI_OPCODE_NOP_IN 0x20
#define ISCSI_OPCODE_SCSI_RSP 0x21
#define ISCSI_OPCODE_SCSI_TMF_RSP 0x22
#define ISCSI_OPCODE_LOGIN_RSP 0x23
#define ISCSI_OPCODE_TEXT_RSP 0x24
#define ISCSI_OPCODE_SCSI_DATA_IN 0x25
#define ISCSI_OPCODE_LOGOUT_RSP 0x26
#define ISCSI_OPCODE_R2T 0x31
#define ISCSI_OPCODE_ASYNC_MSG 0x32
#define ISCSI_OPCODE_VENDOR_T0 0x3c
#define ISCSI_OPCODE_VENDOR_T1 0x3d
#define ISCSI_OPCODE_VENDOR_T2 0x3e
#define ISCSI_OPCODE_REJECT 0x3f
#define ISCSI_BHS_FLAG_FINAL 0x80
//
// iSCSI Basic Header Segment
//
typedef struct _ISCSI_BASIC_HEADER {
UINT8 OpCode;
UINT8 Flags;
UINT16 OpCodeSpecific1;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 OpCodeSpecific2[7];
} ISCSI_BASIC_HEADER;
//
// Defined AHS types, others are reserved.
//
#define ISCSI_AHS_TYPE_EXT_CDB 0x1
#define ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN 0x2
typedef struct _ISCSI_ADDTIONAL_HEADER {
UINT16 Length;
UINT8 Type;
UINT8 TypeSpecific[1];
} ISCSI_ADDITIONAL_HEADER;
typedef struct _ISCSI_BI_EXP_READ_DATA_LEN_AHS {
UINT16 Length;
UINT8 Type;
UINT8 Reserved;
UINT32 ExpReadDataLength;
} ISCSI_BI_EXP_READ_DATA_LEN_AHS;
#define SCSI_CMD_PDU_FLAG_READ 0x40
#define SCSI_CMD_PDU_FLAG_WRITE 0x20
#define ISCSI_CMD_PDU_TASK_ATTR_MASK 0x07
//
// task attributes
//
#define ISCSI_TASK_ATTR_UNTAGGED 0x00
#define ISCSI_TASK_ATTR_SIMPLE 0x01
#define ISCSI_TASK_ATTR_ORDERD 0x02
#define ISCSI_TASK_ATTR_HOQ 0x03
#define ISCSI_TASK_ATTR_ACA 0x04
//
// SCSI Command
//
typedef struct _SCSI_COMMAND {
UINT8 OpCode;
UINT8 Flags;
UINT16 Reserved;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 ExpDataXferLength;
UINT32 CmdSN;
UINT32 ExpStatSN;
UINT8 CDB[16];
} SCSI_COMMAND;
//
// flag bit definitions in SCSI response
//
#define SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW 0x10
#define SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW 0x08
#define SCSI_RSP_PDU_FLAG_OVERFLOW 0x04
#define SCSI_RSP_PDU_FLAG_UNDERFLOW 0x02
//
// iSCSI service response codes
//
#define ISCSI_SERVICE_RSP_COMMAND_COMPLETE_AT_TARGET 0x00
#define ISCSI_SERVICE_RSP_TARGET_FAILURE 0x01
//
// SCSI Response
//
typedef struct _SCSI_RESPONSE {
UINT8 OpCode;
UINT8 Flags;
UINT8 Response;
UINT8 Status;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Reserved[8];
UINT32 InitiatorTaskTag;
UINT32 SNACKTag;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 ExpDataSN;
UINT32 BiReadResidualCount;
UINT32 ResidualCount;
} SCSI_RESPONSE;
typedef struct _ISCSI_SENSE_DATA {
UINT16 Length;
UINT8 Data[2];
} ISCSI_SENSE_DATA;
//
// iSCSI Task Managment Function Request
//
typedef struct _ISCSI_TMF_REQUEST {
UINT8 OpCode;
UINT8 Fuction;
UINT16 Reserved1;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 ReferencedTaskTag;
UINT32 CmdSN;
UINT32 ExpStatSN;
UINT32 RefCmdSN;
UINT32 ExpDataSN;
UINT32 Reserved2[2];
} ISCSI_TMF_REQUEST;
#define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_COMPLETE 0
#define ISCSI_TMF_RSP_PDU_RSP_TASK_NOT_EXIST 1
#define ISCSI_TMF_RSP_PDU_RSP_LUN_NOT_EXIST 2
#define ISCSI_TMF_RSP_PDU_RSP_TASK_STILL_ALLEGIANT 3
#define ISCSI_TMF_RSP_PDU_RSP_TASK_REASSGIN_NOT_SUPPORTED 4
#define ISCSI_TMF_RSP_PDU_RSP_NOT_SUPPORTED 5
#define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_AHTH_FAILED 6
#define ISCSI_TMF_RSP_PDU_RSP_FUNCTION_REJECTED 255
//
// iSCSI Task Management Function Response
//
typedef struct _ISCSI_TMF_RESPONSE {
UINT8 OpCode;
UINT8 Reserved1;
UINT8 Response;
UINT8 Reserved2;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT32 Reserver3[2];
UINT32 InitiatorTaskTag;
UINT32 Reserved4;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 Reserved[3];
} ISCSI_TMF_RESPONSE;
//
// SCSI Data-Out
//
typedef struct _ISCSI_SCSI_DATA_OUT {
UINT8 OpCode;
UINT8 Reserved1[3];
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 Reserved2;
UINT32 ExpStatSN;
UINT32 Reserved3;
UINT32 DataSN;
UINT32 BufferOffset;
UINT32 Reserved4;
} ISCSI_SCSI_DATA_OUT;
#define SCSI_DATA_IN_PDU_FLAG_ACKKNOWLEDGE 0x40
#define SCSI_DATA_IN_PDU_FLAG_OVERFLOW SCSI_RSP_PDU_FLAG_OVERFLOW
#define SCSI_DATA_IN_PDU_FLAG_UNDERFLOW SCSI_RSP_PDU_FLAG_UNDERFLOW
#define SCSI_DATA_IN_PDU_FLAG_STATUS_VALID 0x01
//
// SCSI Data-In
//
typedef struct _ISCSI_SCSI_DATA_IN {
UINT8 OpCode;
UINT8 Flags;
UINT8 Reserved1;
UINT8 Status;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 DataSN;
UINT32 BufferOffset;
UINT32 ResidualCount;
} ISCSI_SCSI_DATA_IN;
#define ISCSI_GET_BUFFER_OFFSET(PduHdr) NTOHL (((ISCSI_SCSI_DATA_IN *) (PduHdr))->BufferOffset)
//
// Ready To Transfer
//
typedef struct _ISCSI_READY_TO_TRANSFER {
UINT8 OpCode;
UINT8 Reserved1[3];
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 R2TSN;
UINT32 BufferOffset;
UINT32 DesiredDataTransferLength;
} ISCSI_READY_TO_TRANSFER;
typedef struct _ISCSI_ASYNC_MESSAGE {
UINT8 OpCode;
UINT8 Reserved1[8];
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 Reserved2;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT8 AsyncEvent;
UINT8 AsyncVCode;
UINT16 Parameter1;
UINT16 Parameter2;
UINT16 Parameter3;
UINT32 Reserved3;
} ISCSI_ASYNC_MESSAGE;
#define ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT 0x80
#define ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE 0x40
//
// Login Request
//
typedef struct _ISCSI_LOGIN_REQUEST {
UINT8 OpCode;
UINT8 Flags;
UINT8 VersionMax;
UINT8 VersionMin;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 ISID[6];
UINT16 TSIH;
UINT32 InitiatorTaskTag;
UINT16 CID;
UINT16 Reserved1;
UINT32 CmdSN;
UINT32 ExpStatSN;
UINT32 Reserved2[4];
} ISCSI_LOGIN_REQUEST;
#define ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT
#define ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE ISCSI_LOGIN_REQ_PDU_FLAG_CONTINUE
#define ISCSI_LOGIN_STATUS_SUCCESS 0
#define ISCSI_LOGIN_STATUS_REDIRECTION 1
#define ISCSI_LOGIN_STATUS_INITIATOR_ERROR 2
#define ISCSI_LOGIN_STATUS_TARGET_ERROR 3
//
// Login Response
//
typedef struct _ISCSI_LOGIN_RESPONSE {
UINT8 OpCode;
UINT8 Flags;
UINT8 VersionMax;
UINT8 VersionActive;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 ISID[6];
UINT16 TSIH;
UINT32 InitiatorTaskTag;
UINT32 Reserved1;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT8 StatusClass;
UINT8 StatusDetail;
UINT8 Reserved2[10];
} ISCSI_LOGIN_RESPONSE;
#define ISCSI_LOGOUT_REASON_CLOSE_SESSION 0
#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION 1
#define ISCSI_LOGOUT_REASON_REMOVE_CONNECTION_FOR_RECOVERY 2
//
// Logout Request
//
typedef struct _ISCSI_LOGOUT_REQUEST {
UINT8 OpCode;
UINT8 ReasonCode;
UINT16 Reserved1;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT32 Reserved2[2];
UINT32 InitiatorTaskTag;
UINT16 CID;
UINT16 Reserved3;
UINT32 CmdSN;
UINT32 ExpStatSN;
UINT32 Reserved4[4];
} ISCSI_LOGOUT_REQUEST;
#define ISCSI_LOGOUT_RESPONSE_SESSION_CLOSED_SUCCESS 0
#define ISCSI_LOGOUT_RESPONSE_CID_NOT_FOUND 1
#define ISCSI_LOGOUT_RESPONSE_RECOVERY_NOT_SUPPORTED 2
#define ISCSI_LOGOUT_RESPONSE_CLEANUP_FAILED 3
//
// Logout Response
//
typedef struct _ISCSI_LOGOUT_RESPONSE {
UINT8 OpCode;
UINT8 Reserved1;
UINT8 Response;
UINT8 Reserved2;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT32 Reserved3[2];
UINT32 InitiatorTaskTag;
UINT32 Reserved4;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 Reserved5;
UINT16 Time2Wait;
UINT16 Time2Retain;
UINT32 Reserved6;
} ISCSI_LOGOUT_RESPONSE;
#define ISCSI_SNACK_REQUEST_TYPE_DATA_OR_R2T 0
#define ISCSI_SNACK_REQUEST_TYPE_STATUS 1
#define ISCSI_SNACK_REQUEST_TYPE_DATA_ACK 2
#define ISCSI_SNACK_REQUEST_TYPE_RDATA 3
//
// SNACK Request
//
typedef struct _ISCSI_SNACK_REQUEST {
UINT8 OpCode;
UINT8 Type;
UINT16 Reserved1;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 Reserved2;
UINT32 ExpStatSN;
UINT32 Reserved[2];
UINT32 BegRun;
UINT32 RunLength;
} ISCSI_SNACK_REQUEST;
//
// Reject
//
typedef struct _ISCSI_REJECT {
UINT8 OpCode;
UINT8 Reserved1;
UINT8 Reason;
UINT8 Reserved2;
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT32 Reserved3[2];
UINT32 InitiatorTaskTag;
UINT32 Reserved4;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 DataSN;
UINT32 Reserved5[2];
} ISCSI_REJECT;
//
// NOP-Out
//
typedef struct _ISCSI_NOP_OUT {
UINT8 OpCode;
UINT8 Reserved1[3];
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 CmdSN;
UINT32 ExpStatSN;
UINT32 Reserved2[4];
} ISCSI_NOP_OUT;
//
// NOP-In
//
typedef struct _ISCSI_NOP_IN {
UINT8 OpCode;
UINT8 Reserved1[3];
UINT8 TotalAHSLength;
UINT8 DataSegmentLength[3];
UINT8 Lun[8];
UINT32 InitiatorTaskTag;
UINT32 TargetTransferTag;
UINT32 StatSN;
UINT32 ExpCmdSN;
UINT32 MaxCmdSN;
UINT32 Reserved2[3];
} ISCSI_NOP_IN;
#define ISCSI_SECURITY_NEGOTIATION 0
#define ISCSI_LOGIN_OPERATIONAL_NEGOTIATION 1
#define ISCSI_FULL_FEATURE_PHASE 3
typedef enum {
ISCSI_DIGEST_NONE,
ISCSI_DIGEST_CRC32
} ISCSI_DIGEST_TYPE;
typedef struct _ISCSI_XFER_CONTEXT {
UINT32 TargetTransferTag;
UINT32 Offset;
UINT32 DesiredLength;
UINT32 ExpDataSN;
} ISCSI_XFER_CONTEXT;
typedef struct _ISCSI_IN_BUFFER_CONTEXT {
UINT8 *InData;
UINT32 InDataLen;
} ISCSI_IN_BUFFER_CONTEXT;
typedef struct _ISCSI_TCB {
NET_LIST_ENTRY Link;
BOOLEAN SoFarInOrder;
UINT32 ExpDataSN;
BOOLEAN FbitReceived;
BOOLEAN StatusXferd;
UINT32 ActiveR2Ts;
UINT32 Response;
CHAR8 *Reason;
UINT32 InitiatorTaskTag;
UINT32 CmdSN;
UINT32 SNACKTag;
ISCSI_XFER_CONTEXT XferContext;
ISCSI_CONNECTION *Conn;
} ISCSI_TCB;
typedef struct _ISCSI_KEY_VALUE_PAIR {
NET_LIST_ENTRY List;
CHAR8 *Key;
CHAR8 *Value;
} ISCSI_KEY_VALUE_PAIR;
//
// function prototypes.
//
VOID
IScsiAttatchConnection (
IN ISCSI_SESSION *Session,
IN ISCSI_CONNECTION *Conn
);
VOID
IScsiDetatchConnection (
IN ISCSI_CONNECTION *Conn
);
EFI_STATUS
IScsiConnLogin (
IN ISCSI_CONNECTION *Conn
);
ISCSI_CONNECTION *
IScsiCreateConnection (
IN ISCSI_DRIVER_DATA *Private,
IN ISCSI_SESSION *Session
);
VOID
IScsiDestroyConnection (
IN ISCSI_CONNECTION *Conn
);
EFI_STATUS
IScsiSessionLogin (
IN ISCSI_DRIVER_DATA *Private
);
EFI_STATUS
IScsiSendLoginReq (
IN ISCSI_CONNECTION *Conn
);
EFI_STATUS
IScsiReceiveLoginRsp (
IN ISCSI_CONNECTION *Conn
);
EFI_STATUS
IScsiAddKeyValuePair (
IN NET_BUF *Pdu,
IN CHAR8 *Key,
IN CHAR8 *Value
);
NET_BUF *
IScsiPrepareLoginReq (
IN ISCSI_CONNECTION *Conn
);
EFI_STATUS
IScsiProcessLoginRsp (
IN ISCSI_CONNECTION *Conn,
IN NET_BUF *Pdu
);
EFI_STATUS
IScsiUpdateTargetAddress (
IN ISCSI_SESSION *Session,
IN CHAR8 *Data,
IN UINT32 Len
);
VOID
IScsiFreeNbufList (
VOID *Arg
);
EFI_STATUS
IScsiReceivePdu (
IN ISCSI_CONNECTION *Conn,
OUT NET_BUF **Pdu,
IN ISCSI_IN_BUFFER_CONTEXT *Context, OPTIONAL
IN BOOLEAN HeaderDigest,
IN BOOLEAN DataDigest,
IN EFI_EVENT TimeoutEvent OPTIONAL
);
EFI_STATUS
IScsiCheckOpParams (
IN ISCSI_CONNECTION *Conn,
IN BOOLEAN Transit
);
EFI_STATUS
IScsiFillOpParams (
IN ISCSI_CONNECTION *Conn,
IN NET_BUF *Pdu
);
EFI_STATUS
IScsiPadSegment (
IN NET_BUF *Pdu,
IN UINT32 Len
);
NET_LIST_ENTRY *
IScsiBuildKeyValueList (
IN CHAR8 *Data,
IN UINT32 Len
);
CHAR8 *
IScsiGetValueByKeyFromList (
IN NET_LIST_ENTRY *KeyValueList,
IN CHAR8 *Key
);
VOID
IScsiFreeKeyValueList (
IN NET_LIST_ENTRY *KeyValueList
);
EFI_STATUS
IScsiNormalizeName (
IN CHAR8 *Name,
IN UINTN Len
);
EFI_STATUS
IScsiExecuteScsiCommand (
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru,
IN UINT8 *Target,
IN UINT64 Lun,
IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
);
EFI_STATUS
IScsiSessionReinstatement (
IN ISCSI_DRIVER_DATA *Private
);
VOID
IScsiSessionInit (
IN ISCSI_SESSION *Session,
IN BOOLEAN Recovery
);
EFI_STATUS
IScsiSessionAbort (
IN ISCSI_SESSION *Session
);
#endif

View File

@ -0,0 +1,550 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiTcp4Io.c
Abstract:
--*/
#include "IScsiImpl.h"
VOID
EFIAPI
Tcp4IoCommonNotify (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
The common notify function associated with various Tcp4Io events.
Arguments:
Event - The event signaled.
Contect - The context.
Returns:
None.
--*/
{
*((BOOLEAN *) Context) = TRUE;
}
EFI_STATUS
Tcp4IoCreateSocket (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller,
IN TCP4_IO_CONFIG_DATA *ConfigData,
IN TCP4_IO *Tcp4Io
)
/*++
Routine Description:
Create a TCP socket with the specified configuration data.
Arguments:
Image - The handle of the driver image.
Controller - The handle of the controller.
ConfigData - The Tcp4 configuration data.
Tcp4Io - The Tcp4Io.
Returns:
EFI_SUCCESS - The TCP socket is created and configured.
other - Failed to create the TCP socket or configure it.
--*/
{
EFI_STATUS Status;
EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP4_CONFIG_DATA Tcp4ConfigData;
EFI_TCP4_OPTION ControlOption;
EFI_TCP4_ACCESS_POINT *AccessPoint;
Tcp4Io->Handle = NULL;
Tcp4Io->ConnToken.CompletionToken.Event = NULL;
Tcp4Io->TxToken.CompletionToken.Event = NULL;
Tcp4Io->RxToken.CompletionToken.Event = NULL;
Tcp4Io->CloseToken.CompletionToken.Event = NULL;
Tcp4 = NULL;
//
// Create the TCP4 child instance and get the TCP4 protocol.
//
Status = NetLibCreateServiceChild (
Controller,
Image,
&gEfiTcp4ServiceBindingProtocolGuid,
&Tcp4Io->Handle
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->OpenProtocol (
Tcp4Io->Handle,
&gEfiTcp4ProtocolGuid,
(VOID **)&Tcp4Io->Tcp4,
Image,
Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Tcp4Io->Image = Image;
Tcp4Io->Controller = Controller;
Tcp4 = Tcp4Io->Tcp4;
//
// Set the configuration parameters.
//
ControlOption.ReceiveBufferSize = 0x200000;
ControlOption.SendBufferSize = 0x200000;
ControlOption.MaxSynBackLog = 0;
ControlOption.ConnectionTimeout = 0;
ControlOption.DataRetries = 6;
ControlOption.FinTimeout = 0;
ControlOption.TimeWaitTimeout = 0;
ControlOption.KeepAliveProbes = 4;
ControlOption.KeepAliveTime = 0;
ControlOption.KeepAliveInterval = 0;
ControlOption.EnableNagle = FALSE;
ControlOption.EnableTimeStamp = FALSE;
ControlOption.EnableWindowScaling = TRUE;
ControlOption.EnableSelectiveAck = FALSE;
ControlOption.EnablePathMtuDiscovery = FALSE;
Tcp4ConfigData.TypeOfService = 8;
Tcp4ConfigData.TimeToLive = 255;
Tcp4ConfigData.ControlOption = &ControlOption;
AccessPoint = &Tcp4ConfigData.AccessPoint;
AccessPoint->UseDefaultAddress = FALSE;
AccessPoint->StationPort = 0;
AccessPoint->RemotePort = ConfigData->RemotePort;
AccessPoint->ActiveFlag = TRUE;
NetCopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
NetCopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
NetCopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS));
//
// Configure the TCP4 protocol.
//
Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) {
//
// the gateway is not zero, add the default route by hand
//
Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
}
//
// Create events for variuos asynchronous operations.
//
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_EVENT,
Tcp4IoCommonNotify,
&Tcp4Io->IsConnDone,
&Tcp4Io->ConnToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_EVENT,
Tcp4IoCommonNotify,
&Tcp4Io->IsTxDone,
&Tcp4Io->TxToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_EVENT,
Tcp4IoCommonNotify,
&Tcp4Io->IsRxDone,
&Tcp4Io->RxToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Status = gBS->CreateEvent (
EFI_EVENT_NOTIFY_SIGNAL,
NET_TPL_EVENT,
Tcp4IoCommonNotify,
&Tcp4Io->IsCloseDone,
&Tcp4Io->CloseToken.CompletionToken.Event
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
Tcp4Io->IsTxDone = FALSE;
Tcp4Io->IsRxDone = FALSE;
return EFI_SUCCESS;
ON_ERROR:
if (Tcp4Io->RxToken.CompletionToken.Event != NULL) {
gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
}
if (Tcp4Io->TxToken.CompletionToken.Event != NULL) {
gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
}
if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) {
gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
}
if (Tcp4 != NULL) {
Tcp4->Configure (Tcp4, NULL);
gBS->CloseProtocol (
Tcp4Io->Handle,
&gEfiTcp4ProtocolGuid,
Image,
Controller
);
}
NetLibDestroyServiceChild (
Controller,
Image,
&gEfiTcp4ServiceBindingProtocolGuid,
Tcp4Io->Handle
);
return Status;
}
VOID
Tcp4IoDestroySocket (
IN TCP4_IO *Tcp4Io
)
/*++
Routine Description:
Destroy the socket.
Arguments:
Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
Returns:
None.
--*/
{
EFI_TCP4_PROTOCOL *Tcp4;
Tcp4 = Tcp4Io->Tcp4;
Tcp4->Configure (Tcp4, NULL);
gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event);
gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event);
gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event);
gBS->CloseProtocol (
Tcp4Io->Handle,
&gEfiTcp4ProtocolGuid,
Tcp4Io->Image,
Tcp4Io->Controller
);
NetLibDestroyServiceChild (
Tcp4Io->Controller,
Tcp4Io->Image,
&gEfiTcp4ServiceBindingProtocolGuid,
Tcp4Io->Handle
);
}
EFI_STATUS
Tcp4IoConnect (
IN TCP4_IO *Tcp4Io,
IN EFI_EVENT Timeout
)
/*++
Routine Description:
Connect to the other endpoint of the TCP socket.
Arguments:
Tcp4Io - The Tcp4Io wrapping the TCP socket.
Timeout - The time to wait for connection done.
Returns:
None.
--*/
{
EFI_TCP4_PROTOCOL *Tcp4;
EFI_STATUS Status;
Tcp4Io->IsConnDone = FALSE;
Tcp4 = Tcp4Io->Tcp4;
Status = Tcp4->Connect (Tcp4, &Tcp4Io->ConnToken);
if (EFI_ERROR (Status)) {
return Status;
}
while (!Tcp4Io->IsConnDone && EFI_ERROR (gBS->CheckEvent (Timeout))) {
Tcp4->Poll (Tcp4);
}
if (!Tcp4Io->IsConnDone) {
Status = EFI_TIMEOUT;
} else {
Status = Tcp4Io->ConnToken.CompletionToken.Status;
}
return Status;
}
VOID
Tcp4IoReset (
IN TCP4_IO *Tcp4Io
)
/*++
Routine Description:
Reset the socket.
Arguments:
Tcp4Io - The Tcp4Io wrapping the TCP socket.
Returns:
None.
--*/
{
EFI_STATUS Status;
EFI_TCP4_PROTOCOL *Tcp4;
Tcp4Io->CloseToken.AbortOnClose = TRUE;
Tcp4Io->IsCloseDone = FALSE;
Tcp4 = Tcp4Io->Tcp4;
Status = Tcp4->Close (Tcp4, &Tcp4Io->CloseToken);
if (EFI_ERROR (Status)) {
return ;
}
while (!Tcp4Io->IsCloseDone) {
Tcp4->Poll (Tcp4);
}
}
EFI_STATUS
Tcp4IoTransmit (
IN TCP4_IO *Tcp4Io,
IN NET_BUF *Packet
)
/*++
Routine Description:
Transmit the Packet to the other endpoint of the socket.
Arguments:
Tcp4Io - The Tcp4Io wrapping the TCP socket.
Packet - The packet to transmit
Returns:
EFI_SUCCESS - The packet is trasmitted.
EFI_OUT_OF_RESOURCES - Failed to allocate memory.
--*/
{
EFI_TCP4_TRANSMIT_DATA *TxData;
EFI_TCP4_PROTOCOL *Tcp4;
EFI_STATUS Status;
TxData = NetAllocatePool (sizeof (EFI_TCP4_TRANSMIT_DATA) + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA));
if (TxData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
TxData->Push = TRUE;
TxData->Urgent = FALSE;
TxData->DataLength = Packet->TotalSize;
//
// Build the fragment table.
//
TxData->FragmentCount = Packet->BlockOpNum;
NetbufBuildExt (Packet, (NET_FRAGMENT *) &TxData->FragmentTable[0], &TxData->FragmentCount);
Tcp4Io->TxToken.Packet.TxData = TxData;
//
// Trasnmit the packet.
//
Tcp4 = Tcp4Io->Tcp4;
Status = Tcp4->Transmit (Tcp4, &Tcp4Io->TxToken);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
while (!Tcp4Io->IsTxDone) {
Tcp4->Poll (Tcp4);
}
Tcp4Io->IsTxDone = FALSE;
Status = Tcp4Io->TxToken.CompletionToken.Status;
ON_EXIT:
NetFreePool (TxData);
return Status;
}
EFI_STATUS
Tcp4IoReceive (
IN TCP4_IO *Tcp4Io,
IN NET_BUF *Packet,
IN BOOLEAN AsyncMode,
IN EFI_EVENT Timeout
)
/*++
Routine Description:
Receive data from the socket.
Arguments:
Tcp4Io - The Tcp4Io which wraps the socket to be destroyeds.
Packet - The buffer to hold the data copy from the soket rx buffer.
AsyncMode - Is this receive asyncronous or not.
Timeout - The time to wait for receiving the amount of data the Packet
can hold.
Returns:
EFI_SUCCESS - The required amount of data is received from the socket.
EFI_OUT_OF_RESOURCES - Failed to allocate momery.
EFI_TIMEOUT - Failed to receive the required amount of data in the
specified time period.
--*/
{
EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP4_RECEIVE_DATA RxData;
EFI_STATUS Status;
NET_FRAGMENT *Fragment;
UINT32 FragmentCount;
UINT32 CurrentFragment;
FragmentCount = Packet->BlockOpNum;
Fragment = NetAllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
if (Fragment == NULL) {
return EFI_OUT_OF_RESOURCES;
}
//
// Build the fragment table.
//
NetbufBuildExt (Packet, Fragment, &FragmentCount);
RxData.FragmentCount = 1;
Tcp4Io->RxToken.Packet.RxData = &RxData;
CurrentFragment = 0;
Tcp4 = Tcp4Io->Tcp4;
Status = EFI_SUCCESS;
while (CurrentFragment < FragmentCount) {
RxData.DataLength = Fragment[CurrentFragment].Len;
RxData.FragmentTable[0].FragmentLength = Fragment[CurrentFragment].Len;
RxData.FragmentTable[0].FragmentBuffer = Fragment[CurrentFragment].Bulk;
Status = Tcp4->Receive (Tcp4, &Tcp4Io->RxToken);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
while (!Tcp4Io->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
//
// Poll until some data is received or something error happens.
//
Tcp4->Poll (Tcp4);
}
if (!Tcp4Io->IsRxDone) {
//
// Timeout occurs, cancel the receive request.
//
Tcp4->Cancel (Tcp4, &Tcp4Io->RxToken.CompletionToken);
Status = EFI_TIMEOUT;
goto ON_EXIT;
} else {
Tcp4Io->IsRxDone = FALSE;
}
if (EFI_ERROR (Tcp4Io->RxToken.CompletionToken.Status)) {
Status = Tcp4Io->RxToken.CompletionToken.Status;
goto ON_EXIT;
}
Fragment[CurrentFragment].Len -= RxData.FragmentTable[0].FragmentLength;
if (Fragment[CurrentFragment].Len == 0) {
CurrentFragment++;
} else {
Fragment[CurrentFragment].Bulk += RxData.FragmentTable[0].FragmentLength;
}
}
ON_EXIT:
NetFreePool (Fragment);
return Status;
}

View File

@ -0,0 +1,93 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
IScsiTcp4Io.h
Abstract:
iSCSI Tcp4 IO related definitions.
--*/
#ifndef _ISCSI_TCP4_IO_H_
#define _ISCSI_TCP4_IO_H_
#include <Library/NetLib.h>
#include <protocol/Tcp4.h>
typedef struct _TCP4_IO_CONFIG_DATA {
EFI_IPv4_ADDRESS LocalIp;
EFI_IPv4_ADDRESS SubnetMask;
EFI_IPv4_ADDRESS Gateway;
EFI_IPv4_ADDRESS RemoteIp;
UINT16 RemotePort;
} TCP4_IO_CONFIG_DATA;
typedef struct _TCP4_IO {
EFI_HANDLE Image;
EFI_HANDLE Controller;
EFI_HANDLE Handle;
EFI_TCP4_PROTOCOL *Tcp4;
EFI_TCP4_CONNECTION_TOKEN ConnToken;
EFI_TCP4_IO_TOKEN TxToken;
EFI_TCP4_IO_TOKEN RxToken;
EFI_TCP4_CLOSE_TOKEN CloseToken;
BOOLEAN IsConnDone;
BOOLEAN IsTxDone;
BOOLEAN IsRxDone;
BOOLEAN IsCloseDone;
} TCP4_IO;
EFI_STATUS
Tcp4IoCreateSocket (
IN EFI_HANDLE Image,
IN EFI_HANDLE Controller,
IN TCP4_IO_CONFIG_DATA *ConfigData,
IN TCP4_IO *Tcp4Io
);
VOID
Tcp4IoDestroySocket (
IN TCP4_IO *Tcp4Io
);
EFI_STATUS
Tcp4IoConnect (
IN TCP4_IO *Tcp4Io,
IN EFI_EVENT Timeout
);
VOID
Tcp4IoReset (
IN TCP4_IO *Tcp4Io
);
EFI_STATUS
Tcp4IoTransmit (
IN TCP4_IO *Tcp4Io,
IN NET_BUF *Packet
);
EFI_STATUS
Tcp4IoReceive (
IN TCP4_IO *Tcp4Io,
IN NET_BUF *Packet,
IN BOOLEAN AsyncMode,
IN EFI_EVENT Timeout
);
#endif

View File

@ -0,0 +1,335 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
Md5.c
Abstract:
Implementation of MD5 algorithm
--*/
#include "Md5.h"
STATIC CONST UINT32 MD5_K[][2] = {
{ 0, 1 },
{ 1, 5 },
{ 5, 3 },
{ 0, 7 }
};
STATIC CONST UINT32 MD5_S[][4] = {
{ 7, 22, 17, 12 },
{ 5, 20, 14, 9 },
{ 4, 23, 16 ,11 },
{ 6, 21, 15, 10 },
};
STATIC CONST UINT32 MD5_T[] = {
0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
};
STATIC CONST UINT8 Md5HashPadding[] =
{
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//
// ROTATE_LEFT rotates x left n bits.
//
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
#define SA S[j & 3]
#define SB S[(j + 1) & 3]
#define SC S[(j + 2) & 3]
#define SD S[(j + 3) & 3]
//
// TF1, TF2, TF3, TF4 are basic MD5 transform functions
//
UINT32 TF1 (UINT32 A, UINT32 B, UINT32 C)
{
return (A & B) | (~A & C);
}
UINT32 TF2 (UINT32 A, UINT32 B, UINT32 C)
{
return (A & C) | (B & ~C);
}
UINT32 TF3 (UINT32 A, UINT32 B, UINT32 C)
{
return A ^ B ^ C;
}
UINT32 TF4 (UINT32 A, UINT32 B, UINT32 C)
{
return B ^ (A | ~C);
}
typedef
UINT32
(*MD5_TRANSFORM_FUNC) (
IN UINT32 A,
IN UINT32 B,
IN UINT32 C
);
STATIC CONST MD5_TRANSFORM_FUNC MD5_F[] = {
TF1,
TF2,
TF3,
TF4
};
STATIC
VOID
MD5Transform (
IN MD5_CTX *Md5Ctx
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
{
UINT32 i;
UINT32 j;
UINT32 S[MD5_HASHSIZE >> 2];
UINT32 *X;
UINT32 k;
UINT32 t;
X = (UINT32 *) Md5Ctx->M;
//
// Copy MD5 states to S
//
NetCopyMem (S, Md5Ctx->States, MD5_HASHSIZE);
t = 0;
for (i = 0; i < 4; i++) {
k = MD5_K[i][0];
for (j = 16; j > 0; j--) {
SA += (*MD5_F[i]) (SB, SC, SD) + X[k] + MD5_T[t];
SA = ROTATE_LEFT (SA, MD5_S[i][j & 3]);
SA += SB;
k += MD5_K[i][1];
k &= 15;
t++;
}
}
for (i = 0; i < 4; i++) {
Md5Ctx->States[i] += S[i];
}
}
STATIC
VOID
MD5UpdateBlock (
IN MD5_CTX *Md5Ctx,
IN CONST UINT8 *Data,
IN UINTN DataLen
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Data - GC_TODO: add argument description
DataLen - GC_TODO: add argument description
Returns:
GC_TODO: add return values
--*/
{
UINTN Limit;
for (Limit = 64 - Md5Ctx->Count; DataLen >= 64 - Md5Ctx->Count; Limit = 64) {
NetCopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, Limit);
MD5Transform (Md5Ctx);
Md5Ctx->Count = 0;
Data += Limit;
DataLen -= Limit;
}
NetCopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, DataLen);
Md5Ctx->Count += DataLen;
}
EFI_STATUS
MD5Init (
IN MD5_CTX *Md5Ctx
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
{
NetZeroMem (Md5Ctx, sizeof (*Md5Ctx));
//
// Set magic initialization constants.
//
Md5Ctx->States[0] = 0x67452301;
Md5Ctx->States[1] = 0xefcdab89;
Md5Ctx->States[2] = 0x98badcfe;
Md5Ctx->States[3] = 0x10325476;
return EFI_SUCCESS;
}
EFI_STATUS
MD5Update (
IN MD5_CTX *Md5Ctx,
IN VOID *Data,
IN UINTN DataLen
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Data - GC_TODO: add argument description
DataLen - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
{
if (EFI_ERROR (Md5Ctx->Status)) {
return Md5Ctx->Status;
}
MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) Data, DataLen);
Md5Ctx->Length += DataLen;
return EFI_SUCCESS;
}
EFI_STATUS
MD5Final (
IN MD5_CTX *Md5Ctx,
OUT UINT8 *HashVal
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
HashVal - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
{
UINTN PadLength;
if (Md5Ctx->Status == EFI_ALREADY_STARTED) {
//
// Store Hashed value & Zeroize sensitive context information.
//
NetCopyMem (HashVal, (UINT8 *) Md5Ctx->States, MD5_HASHSIZE);
NetZeroMem ((UINT8 *)Md5Ctx, sizeof (*Md5Ctx));
return EFI_SUCCESS;
}
if (EFI_ERROR (Md5Ctx->Status)) {
return Md5Ctx->Status;
}
PadLength = Md5Ctx->Count >= 56 ? 120 : 56;
PadLength -= Md5Ctx->Count;
MD5UpdateBlock (Md5Ctx, Md5HashPadding, PadLength);
Md5Ctx->Length = LShiftU64 (Md5Ctx->Length, 3);
MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) &Md5Ctx->Length, 8);
NetZeroMem (Md5Ctx->M, sizeof (Md5Ctx->M));
Md5Ctx->Length = 0;
Md5Ctx->Status = EFI_ALREADY_STARTED;
return MD5Final (Md5Ctx, HashVal);
}

View File

@ -0,0 +1,108 @@
/*++
Copyright (c) 2007 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.
Module Name:
Md5.h
Abstract:
Header file for Md5
--*/
#ifndef _MD5_H_
#define _MD5_H_
#include <uefi/UefiBaseType.h>
#include <Library/BaseLib.h>
#include <Library/NetLib.h>
#define MD5_HASHSIZE 16
typedef struct _MD5_CTX {
EFI_STATUS Status;
UINT64 Length;
UINT32 States[MD5_HASHSIZE / sizeof (UINT32)];
UINT8 M[64];
UINTN Count;
} MD5_CTX;
EFI_STATUS
MD5Init (
IN MD5_CTX *Md5Ctx
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
;
EFI_STATUS
MD5Update (
IN MD5_CTX *Md5Ctx,
IN VOID *Data,
IN UINTN DataLen
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
Data - GC_TODO: add argument description
DataLen - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
;
EFI_STATUS
MD5Final (
IN MD5_CTX *Md5Ctx,
OUT UINT8 *HashVal
)
/*++
Routine Description:
GC_TODO: Add function description
Arguments:
Md5Ctx - GC_TODO: add argument description
HashVal - GC_TODO: add argument description
Returns:
EFI_SUCCESS - GC_TODO: Add description for return value
--*/
;
#endif // _MD5_H