4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The implementation of iSCSI protocol based on RFC3720.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "IScsiImpl.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32 mDataSegPad = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Attach the iSCSI connection to the iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The iSCSI connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiAttatchConnection (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_SESSION *Session,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&Session->Conns, &Conn->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Session = Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->NumConns++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Detach the iSCSI connection from the session it belongs to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The iSCSI connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiDetatchConnection (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Conn->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Session->NumConns--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Session = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check the sequence number according to RFC3720.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] ExpSN The currently expected sequence number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] NewSN The sequence number to check.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The check passed and the ExpSN is increased.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_READY Response was sent due to a retransmission request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiCheckSN (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT UINT32 *ExpSN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 NewSN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ISCSI_SEQ_EQ (NewSN, *ExpSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_SEQ_LT (NewSN, *ExpSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Duplicate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_READY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Advance the ExpSN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (*ExpSN)++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Update the sequence numbers for the iSCSI command.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] MaxCmdSN Maximum CmdSN from the target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] ExpCmdSN Next expected CmdSN from the target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiUpdateCmdSN (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_SESSION *Session,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 MaxCmdSN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 ExpCmdSN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_SEQ_LT (MaxCmdSN, ExpCmdSN - 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_SEQ_GT (MaxCmdSN, Session->MaxCmdSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxCmdSN = MaxCmdSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_SEQ_GT (ExpCmdSN, Session->ExpCmdSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ExpCmdSN = ExpCmdSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This function does the iSCSI connection login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The iSCSI connection to login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Timeout The timeout value in millisecond.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI connection is logged into the iSCSI target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TIMEOUT Timeout occurred during the login procedure.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiConnLogin (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 Timeout
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start the timer, and wait Timeout seconds to establish the TCP connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->SetTimer (Conn->TimeoutEvent, TimerRelative, Timeout * TICKS_PER_MS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Try to establish the tcp connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoConnect (&Conn->TcpIo, Conn->TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SetTimer (Conn->TimeoutEvent, TimerCancel, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->State = CONN_STATE_IN_LOGIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Connection is established, start the iSCSI Login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiSendLoginReq (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiReceiveLoginRsp (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (Conn->CurrentStage != ISCSI_FULL_FEATURE_PHASE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reset the iSCSI connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The iSCSI connection to reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiConnReset (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpIoReset (&Conn->TcpIo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a TCP connection for the iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Session Points to the iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The newly created iSCSI connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncISCSI_CONNECTION *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiCreateConnection (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_SESSION *Session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_DRIVER_DATA *Private;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION_CONFIG_NVDATA *NvData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION *Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP_IO_CONFIG_DATA TcpIoConfig;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP4_IO_CONFIG_DATA *Tcp4IoConfig;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TCP6_IO_CONFIG_DATA *Tcp6IoConfig;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Private = Session->Private;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NvData = &Session->ConfigData->SessionConfigData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = AllocateZeroPool (sizeof (ISCSI_CONNECTION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Signature = ISCSI_CONNECTION_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->State = CONN_STATE_FREE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->CurrentStage = ISCSI_SECURITY_NEGOTIATION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->NextStage = ISCSI_LOGIN_OPERATIONAL_NEGOTIATION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->AuthStep = ISCSI_AUTH_INITIAL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->ExpStatSN = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->PartialReqSent = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->PartialRspRcvd = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->ParamNegotiated = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Cid = Session->NextCid++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->Ipv6Flag = mPrivate->Ipv6Flag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CreateEvent (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVT_TIMER,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TPL_CALLBACK,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Conn->TimeoutEvent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufQueInit (&Conn->RspQue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the default connection-only parameters.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->MaxRecvDataSegmentLength = DEFAULT_MAX_RECV_DATA_SEG_LEN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->HeaderDigest = IScsiDigestNone;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->DataDigest = IScsiDigestNone;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Conn->Ipv6Flag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp4IoConfig = &TcpIoConfig.Tcp4IoConfigData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Tcp4IoConfig->LocalIp, &NvData->LocalIp, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Tcp4IoConfig->SubnetMask, &NvData->SubnetMask, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Tcp4IoConfig->Gateway, &NvData->Gateway, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Tcp4IoConfig->RemoteIp, &NvData->TargetIp, sizeof (EFI_IPv4_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp4IoConfig->RemotePort = NvData->TargetPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp4IoConfig->ActiveFlag = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp6IoConfig = &TcpIoConfig.Tcp6IoConfigData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&Tcp6IoConfig->RemoteIp, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp6IoConfig->RemotePort = NvData->TargetPort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcp6IoConfig->ActiveFlag = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the TCP IO for this connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoCreateSocket (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Private->Image,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Private->Controller,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8) (!Conn->Ipv6Flag ? TCP_VERSION_4: TCP_VERSION_6),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &TcpIoConfig,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Conn->TcpIo
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseEvent (Conn->TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Destroy an iSCSI connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The connection to destroy.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiDestroyConnection (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TcpIoDestroySocket (&Conn->TcpIo);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufQueFlush (&Conn->RspQue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseEvent (Conn->TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Login the iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI session login procedure finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NO_MEDIA There was a media error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSessionLogin (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_SESSION *Session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION *Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *Tcp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_GUID *ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 RetryCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN MediaPresent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check media status before session login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MediaPresent = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetLibDetectMedia (Session->Private->Controller, &MediaPresent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!MediaPresent) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NO_MEDIA;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set session identifier
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Session->Isid, Session->ConfigData->SessionConfigData.IsId, 6);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RetryCount = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a connection for the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = IScsiCreateConnection (Session);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAttatchConnection (Session, Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Login througth the newly created connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiConnLogin (Conn, Session->ConfigData->SessionConfigData.ConnectTimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiConnReset (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiDetatchConnection (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiDestroyConnection (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status != EFI_TIMEOUT) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RetryCount++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (RetryCount <= Session->ConfigData->SessionConfigData.ConnectRetryCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->State = SESSION_STATE_LOGGED_IN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!mPrivate->Ipv6Flag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid = &gEfiTcp4ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid = &gEfiTcp6ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->OpenProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->TcpIo.Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &Tcp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Private->Image,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Private->ExtScsiPassThruHandle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT_EFI_ERROR (Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Wait for IPsec negotiation, then try to login the iSCSI session again.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI session login procedure finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSessionReLogin (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_SESSION *Session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS TimerStatus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_EVENT Timer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->SetTimer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Timer,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimerRelative,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_WAIT_IPSEC_TIMEOUT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseEvent (Timer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync do {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimerStatus = gBS->CheckEvent (Timer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (TimerStatus)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiSessionLogin (Session);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } while (TimerStatus == EFI_NOT_READY);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseEvent (Timer);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build and send the iSCSI login request to the iSCSI target according to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the current login stage.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The connection in the iSCSI login phase.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI login request PDU is built and sent on this
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Some kind of device error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSendLoginReq (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build the Login Request PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = IScsiPrepareLoginReq (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send it to the iSCSI target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoTransmit (&Conn->TcpIo, Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Receive and process the iSCSI login response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The connection in the iSCSI login phase.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI login response PDU is received and processed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiReceiveLoginRsp (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receive the iSCSI login response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiReceivePdu (Conn, &Pdu, NULL, FALSE, FALSE, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pdu != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A Login Response is received; process it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiProcessLoginRsp (Conn, Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Add an iSCSI key-value pair as a string into the data segment of the Login Request PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The DataSegmentLength and the actual size of the net buffer containing this PDU will be
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync updated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Pdu The iSCSI PDU whose data segment the key-value pair will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync be added to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Key The key name string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Value The value string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The key-value pair is added to the PDU's data segment and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the correspondence length fields are updated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There is not enough space in the PDU to add the key-value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync pair.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR There is no such data in the net buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiAddKeyValuePair (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CHAR8 *Key,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CHAR8 *Value
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataSegLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 KeyLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 ValueLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 TotalLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_LOGIN_REQUEST *LoginReq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq = (ISCSI_LOGIN_REQUEST *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LoginReq == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSegLen = NTOH24 (LoginReq->DataSegmentLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyLen = (UINT32) AsciiStrLen (Key);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ValueLen = (UINT32) AsciiStrLen (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // 1 byte for the key value separator '=' and 1 byte for the null
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // delimiter after the value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TotalLen = KeyLen + 1 + ValueLen + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate the space for the key-value pair.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = (CHAR8 *) NetbufAllocSpace (Pdu, TotalLen, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Data == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add the key.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Data, Key, KeyLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data += KeyLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Data = '=';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add the value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Data, Value, ValueLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data += ValueLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Data = '\0';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the DataSegmentLength
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_DATASEG_LEN (LoginReq, DataSegLen + TotalLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Prepare the iSCSI login request to be sent according to the current login status.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The connection in the iSCSI login phase.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The pointer to the net buffer containing the iSCSI login request built.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiPrepareLoginReq (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_LOGIN_REQUEST *LoginReq;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NetbufAlloc (sizeof (ISCSI_LOGIN_REQUEST) + DEFAULT_MAX_RECV_DATA_SEG_LEN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Nbuf == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq = (ISCSI_LOGIN_REQUEST *) NetbufAllocSpace (Nbuf, sizeof (ISCSI_LOGIN_REQUEST), NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (LoginReq != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (LoginReq, sizeof (ISCSI_LOGIN_REQUEST));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Init the login request pdu
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_OPCODE (LoginReq, ISCSI_OPCODE_LOGIN_REQ, ISCSI_REQ_IMMEDIATE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_STAGES (LoginReq, Conn->CurrentStage, Conn->NextStage);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->VersionMax = ISCSI_VERSION_MAX;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->VersionMin = ISCSI_VERSION_MIN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->Tsih = HTONS (Session->Tsih);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->InitiatorTaskTag = HTONL (Session->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->Cid = HTONS (Conn->Cid);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->CmdSN = HTONL (Session->CmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For the first Login Request on a coonection this is ExpStatSN for the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // old connection, and this field is only valid if the Login Request restarts
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For subsequent Login Requests it is used to acknowledge the Login Responses
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // with their increasing StatSN values.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginReq->ExpStatSN = HTONL (Conn->ExpStatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (LoginReq->Isid, Session->Isid, sizeof (LoginReq->Isid));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn->PartialRspRcvd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A partial response. The initiator must send an empty Login Request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Conn->CurrentStage) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_SECURITY_NEGOTIATION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Both none authentication and CHAP authentication share the CHAP path.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCHAPToSendReq (Conn, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only negotiate the paramter once.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Conn->ParamNegotiated) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFillOpParams (Conn, Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // An error occurs...
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Nbuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Nbuf = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Pad the data segment if needed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiPadSegment (Nbuf, ISCSI_GET_DATASEG_LEN (LoginReq));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check whether we will issue the stage transition signal?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->TransitInitiated = ISCSI_FLAG_ON (LoginReq, ISCSI_LOGIN_REQ_PDU_FLAG_TRANSIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Nbuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the iSCSI Login Response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The connection on which the iSCSI login response is received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Pdu The iSCSI login response PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI login response PDU is processed, and all checks are passed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_MEDIA_CHANGED Target is redirected.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiProcessLoginRsp (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT NET_BUF *Pdu
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_LOGIN_RESPONSE *LoginRsp;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Transit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 CurrentStage;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 NextStage;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataSegLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginRsp = (ISCSI_LOGIN_RESPONSE *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (LoginRsp == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ISCSI_CHECK_OPCODE (LoginRsp, ISCSI_OPCODE_LOGIN_RSP)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It is not a Login Response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the data segment, if any.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSegLen = ISCSI_GET_DATASEG_LEN (LoginRsp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSegLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = NetbufGetByte (Pdu, sizeof (ISCSI_LOGIN_RESPONSE), NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the status class in the login response PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (LoginRsp->StatusClass) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_LOGIN_STATUS_SUCCESS:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Just break here; the response and the data segment will be processed later.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_LOGIN_STATUS_REDIRECTION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The target may be moved to a different address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSeg == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Process the TargetAddress key-value strings in the data segment to update the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // target address info.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiUpdateTargetAddress (Session, (CHAR8 *) DataSeg, DataSegLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Session will be restarted on this error status because the Target is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // redirected by this Login Response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_MEDIA_CHANGED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initiator Error, Target Error, or any other undefined error code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The status is success; extract the wanted fields from the header segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Transit = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_TRANSIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Continue = ISCSI_FLAG_ON (LoginRsp, ISCSI_LOGIN_RSP_PDU_FLAG_CONTINUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CurrentStage = ISCSI_GET_CURRENT_STAGE (LoginRsp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NextStage = ISCSI_GET_NEXT_STAGE (LoginRsp);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginRsp->InitiatorTaskTag = NTOHL (LoginRsp->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Transit && Continue) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (CurrentStage != Conn->CurrentStage) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (!Conn->TransitInitiated && Transit) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Transit && (NextStage != Conn->NextStage)) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (CompareMem (Session->Isid, LoginRsp->Isid, sizeof (LoginRsp->Isid)) != 0) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (LoginRsp->InitiatorTaskTag != Session->InitiatorTaskTag)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // A Login Response with the C bit set to 1 MUST have the T bit set to 0.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The CSG in the Login Response MUST be the same with the I-end of this connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The T bit can't be 1 if the last Login Response sent by the initiator doesn't
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // initiate the transistion.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The NSG MUST be the same with the I-end of this connection if Transit is required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The ISID in the Login Response MUST be the same with this session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginRsp->StatSN = NTOHL (LoginRsp->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginRsp->ExpCmdSN = NTOHL (LoginRsp->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LoginRsp->MaxCmdSN = NTOHL (LoginRsp->MaxCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Conn->CurrentStage == ISCSI_SECURITY_NEGOTIATION) && (Conn->AuthStep == ISCSI_AUTH_INITIAL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // If the Login Request is a leading Login Request, the target MUST use
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the value presented in CmdSN as the target value for ExpCmdSN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Session->State == SESSION_STATE_FREE) && (Session->CmdSN != LoginRsp->ExpCmdSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It's the initial Login Response, initialize the local ExpStatSN, MaxCmdSN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // and ExpCmdSN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->ExpStatSN = LoginRsp->StatSN + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxCmdSN = LoginRsp->MaxCmdSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ExpCmdSN = LoginRsp->ExpCmdSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the StatSN of this PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Conn->ExpStatSN, LoginRsp->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the MaxCmdSN and ExpCmdSN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiUpdateCmdSN (Session, LoginRsp->MaxCmdSN, LoginRsp->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Trim off the header segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (Pdu, sizeof (ISCSI_LOGIN_RESPONSE), NET_BUF_HEAD);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Queue this login response first in case it's a partial response so that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // later when the full response list is received we can combine these scattered
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // responses' data segment and then process it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_GET_REF (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufQueAppend (&Conn->RspQue, Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->PartialRspRcvd = Continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Continue) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It is a partial response; must wait for another or more Request/Response
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // conversations to get the full response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (CurrentStage) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_SECURITY_NEGOTIATION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // In security negotiation stage, let CHAP module handle it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->AuthType != ISCSI_AUTH_TYPE_KRB) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCHAPOnRspReceived (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_LOGIN_OPERATIONAL_NEGOTIATION:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Response received with negotiation response on iSCSI parameters: check them.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckOpParams (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->ParamNegotiated = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Should never get here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Transit && (Status == EFI_SUCCESS)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Do the state transition.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->CurrentStage = Conn->NextStage;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn->CurrentStage == ISCSI_LOGIN_OPERATIONAL_NEGOTIATION) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->NextStage = ISCSI_FULL_FEATURE_PHASE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // CurrentStage is iSCSI Full Feature. It is the Login-Final Response;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // get the TSIH from the Login Response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Tsih = NTOHS (LoginRsp->Tsih);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Flush the response(s) received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufQueFlush (&Conn->RspQue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Updated the target information according the data received in the iSCSI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync login response with an target redirection status.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data segment that should contain the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TargetAddress key-value list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The target address is updated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_FOUND The TargetAddress key is not found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiUpdateTargetAddress (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_SESSION *Session,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CHAR8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *KeyValueList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *TargetAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *IpStr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Number;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 IpMode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValueList = IScsiBuildKeyValueList (Data, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (KeyValueList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_NOT_FOUND;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (TRUE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TargetAddress = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_ADDRESS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TargetAddress == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NET_IS_DIGIT (TargetAddress[0])) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The domainname of the target may be presented in three formats: a DNS host name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // a dotted-decimal IPv4 address, or a bracketed IPv6 address. Only accept dotted
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // IPv4 address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpStr = TargetAddress;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((*TargetAddress != 0) && (*TargetAddress != ':') && (*TargetAddress != ',')) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NULL, ':', or ',' ends the IPv4 string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TargetAddress++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*TargetAddress == ',') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Comma and the portal group tag MUST be ommitted if the TargetAddress is sent
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // as the result of a redirection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (*TargetAddress == ':') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *TargetAddress = '\0';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TargetAddress++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Number = AsciiStrDecimalToUintn (TargetAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Number > 0xFFFF) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ConfigData->SessionConfigData.TargetPort = (UINT16) Number;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The string only contains the IPv4 address. Use the well-known port.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ConfigData->SessionConfigData.TargetPort = ISCSI_WELL_KNOWN_PORT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the target IP address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->ConfigData->SessionConfigData.IpMode < IP_MODE_AUTOCONFIG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpMode = Session->ConfigData->SessionConfigData.IpMode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpMode = Session->ConfigData->AutoConfigureMode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiAsciiStrToIp (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpStr,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IpMode,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Session->ConfigData->SessionConfigData.TargetIp
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync continue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeKeyValueList (KeyValueList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The callback function to free the net buffer list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Arg The opaque parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiFreeNbufList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *Arg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Arg != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFreeList ((LIST_ENTRY *) Arg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Arg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The callback function called in NetBufFree; it does nothing.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Arg The opaque parameter.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNbufExtFree (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *Arg
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Receive an iSCSI response PDU. An iSCSI response PDU contains an iSCSI PDU header and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync an optional data segment. The two parts will be put into two blocks of buffers in the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync net buffer. The digest check will be conducted in this function if needed and the digests
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync will be trimmed from the PDU buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The iSCSI connection to receive data from.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Pdu The received iSCSI pdu.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Context The context used to describe information on the caller provided
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync buffer to receive data segment of the iSCSI pdu. It is optional.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] HeaderDigest Whether there will be header digest received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataDigest Whether there will be data digest.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TimeoutEvent The timeout event. It is optional.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS An iSCSI pdu is received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiReceivePdu (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT NET_BUF **Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_IN_BUFFER_CONTEXT *Context, OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN HeaderDigest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN DataDigest,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EVENT TimeoutEvent OPTIONAL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *NbufList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *PduHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Header;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 PadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 InDataOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_FRAGMENT Fragment[2];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FragmentCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 PadAndCRC32[2];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NbufList = AllocatePool (sizeof (LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NbufList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The header digest will be received together with the PDU header, if exists.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = sizeof (ISCSI_BASIC_HEADER) + (HeaderDigest ? sizeof (UINT32) : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduHdr = NetbufAlloc (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Header = NetbufAllocSpace (PduHdr, Len, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Header != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &PduHdr->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // First step, receive the BHS of the PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoReceive (&Conn->TcpIo, PduHdr, FALSE, TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (HeaderDigest) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // TODO: check the header-digest.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Trim off the digest.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (PduHdr, sizeof (UINT32), NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = ISCSI_GET_DATASEG_LEN (Header);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // No data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto FORM_PDU;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get the length of the padding bytes of the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadLen = ISCSI_GET_PAD_LEN (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (ISCSI_GET_OPCODE (Header)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_SCSI_DATA_IN:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // To reduce memory copy overhead, try to use the buffer described by Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if the PDU is an iSCSI SCSI data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InDataOffset = ISCSI_GET_BUFFER_OFFSET (Header);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Context == NULL) || ((InDataOffset + Len) > Context->InDataLen)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[0].Len = Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[0].Bulk = Context->InData + InDataOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataDigest || (PadLen != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The data segment is padded. Use two fragments to receive it:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the first to receive the useful data; the second to receive the padding.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[1].Len = PadLen + (DataDigest ? sizeof (UINT32) : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[1].Bulk = (UINT8 *)PadAndCRC32 + (4 - PadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FragmentCount = 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FragmentCount = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = NetbufFromExt (&Fragment[0], FragmentCount, 0, 0, IScsiNbufExtFree, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSeg == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_SCSI_RSP:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_NOP_IN:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_LOGIN_RSP:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_TEXT_RSP:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_ASYNC_MSG:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_REJECT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T0:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T2:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate buffer to receive the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len += PadLen + (DataDigest ? sizeof (UINT32) : 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = NetbufAlloc (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSeg == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufAllocSpace (DataSeg, Len, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &DataSeg->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Receive the data segment with the data digest, if any.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoReceive (&Conn->TcpIo, DataSeg, FALSE, TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataDigest) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // TODO: Check the data digest.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (DataSeg, sizeof (UINT32), NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Trim off the padding bytes in the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufTrim (DataSeg, PadLen, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncFORM_PDU:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Form the pdu from a list of pdu segments.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Pdu = NetbufFromBufList (NbufList, 0, 0, IScsiFreeNbufList, NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*Pdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the Nbufs in this NbufList and the NbufList itself.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check and get the result of the parameter negotiation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Conn The connection in iSCSI login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The parmeter check is passed and negotiation is finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiCheckOpParams (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_CONNECTION *Conn
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *KeyValueList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Value;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN NumericValue;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Conn->RspQue.BufNum != 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = Conn->RspQue.BufSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = AllocatePool (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Data == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufQueCopy (&Conn->RspQue, 0, Len, (UINT8 *) Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Extract the Key-Value pairs into a list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValueList = IScsiBuildKeyValueList (Data, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (KeyValueList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // HeaderDigest
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_HEADER_DIGEST);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AsciiStrCmp (Value, "CRC32") == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn->HeaderDigest != IScsiDigestCRC32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->HeaderDigest = IScsiDigestNone;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DataDigest
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_DIGEST);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AsciiStrCmp (Value, "CRC32") == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Conn->DataDigest != IScsiDigestCRC32) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (AsciiStrCmp (Value, ISCSI_KEY_VALUE_NONE) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->DataDigest = IScsiDigestNone;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ErrorRecoveryLevel: result fuction is Minimum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_ERROR_RECOVERY_LEVEL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumericValue > 2) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ErrorRecoveryLevel = (UINT8) MIN (Session->ErrorRecoveryLevel, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // InitialR2T: result function is OR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Session->InitialR2T) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_INITIAL_R2T);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->InitialR2T = (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ImmediateData: result function is AND.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_IMMEDIATE_DATA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ImmediateData = (BOOLEAN) (Session->ImmediateData && (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // MaxRecvDataSegmentLength is declarative.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->MaxRecvDataSegmentLength = (UINT32) IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // MaxBurstLength: result funtion is Mininum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_MAX_BURST_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxBurstLength = (UINT32) MIN (Session->MaxBurstLength, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // FirstBurstLength: result function is Minimum. Irrelevant when InitialR2T=Yes and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ImmediateData=No.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!(Session->InitialR2T && !Session->ImmediateData)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_FIRST_BURST_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->FirstBurstLength = (UINT32) MIN (Session->FirstBurstLength, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // MaxConnections: result function is Minimum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_MAX_CONNECTIONS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NumericValue == 0) || (NumericValue > 65535)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxConnections = (UINT32) MIN (Session->MaxConnections, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DataPDUInOrder: result function is OR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Session->DataPDUInOrder) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_PDU_IN_ORDER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DataPDUInOrder = (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DataSequenceInorder: result function is OR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Session->DataSequenceInOrder) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_SEQUENCE_IN_ORDER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DataSequenceInOrder = (BOOLEAN) (AsciiStrCmp (Value, "Yes") == 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DefaultTime2Wait: result function is Maximum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DEFAULT_TIME2WAIT);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumericValue == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Wait = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (NumericValue > 3600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Wait = (UINT32) MAX (Session->DefaultTime2Wait, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DefaultTime2Retain: result function is Minimum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DEFAULT_TIME2RETAIN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumericValue == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Retain = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (NumericValue > 3600) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Retain = (UINT32) MIN (Session->DefaultTime2Retain, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // MaxOutstandingR2T: result function is Minimum.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_MAX_OUTSTANDING_R2T);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Value == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumericValue = IScsiNetNtoi (Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((NumericValue == 0) || (NumericValue > 65535)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxOutstandingR2T = (UINT16) MIN (Session->MaxOutstandingR2T, NumericValue);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove declarative key-value pairs, if any.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_SESSION_TYPE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_ALIAS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_TARGET_PORTAL_GROUP_TAG);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the key-value that may not needed for result function is OR.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_INITIAL_R2T);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_PDU_IN_ORDER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_SEQUENCE_IN_ORDER);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove irrelevant parameter, if any.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->InitialR2T && !Session->ImmediateData) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_FIRST_BURST_LENGTH);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (IsListEmpty (KeyValueList)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Succeed if no more keys in the list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_ERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeKeyValueList (KeyValueList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Data);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fill the operational parameters.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The connection in iSCSI login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Pdu The iSCSI login request PDU to fill the parameters.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiFillOpParams (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT NET_BUF *Pdu
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 Value[256];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", (Conn->HeaderDigest == IScsiDigestCRC32) ? "None,CRC32" : "None");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_HEADER_DIGEST, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", (Conn->DataDigest == IScsiDigestCRC32) ? "None,CRC32" : "None");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_DATA_DIGEST, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->ErrorRecoveryLevel);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_ERROR_RECOVERY_LEVEL, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", Session->InitialR2T ? "Yes" : "No");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_INITIAL_R2T, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", Session->ImmediateData ? "Yes" : "No");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_IMMEDIATE_DATA, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", MAX_RECV_DATA_SEG_LEN_IN_FFP);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_MAX_RECV_DATA_SEGMENT_LENGTH, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->MaxBurstLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_MAX_BURST_LENGTH, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->FirstBurstLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_FIRST_BURST_LENGTH, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->MaxConnections);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_MAX_CONNECTIONS, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", Session->DataPDUInOrder ? "Yes" : "No");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_DATA_PDU_IN_ORDER, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%a", Session->DataSequenceInOrder ? "Yes" : "No");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_DATA_SEQUENCE_IN_ORDER, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->DefaultTime2Wait);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_DEFAULT_TIME2WAIT, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->DefaultTime2Retain);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_DEFAULT_TIME2RETAIN, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsciiSPrint (Value, sizeof (Value), "%d", Session->MaxOutstandingR2T);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiAddKeyValuePair (Pdu, ISCSI_KEY_MAX_OUTSTANDING_R2T, Value);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pad the iSCSI AHS or data segment to an integer number of 4 byte words.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Pdu The iSCSI pdu which contains segments to pad.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len The length of the last segment in the PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The segment is padded or there is no need to pad it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES There is not enough remaining free space to add the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync padding bytes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiPadSegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 PadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadLen = ISCSI_GET_PAD_LEN (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = NetbufAllocSpace (Pdu, PadLen, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Data == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (Data, PadLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build a key-value list from the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data segment containing the key-value pairs.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The key-value list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncLIST_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiBuildKeyValueList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CHAR8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *ListHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_KEY_VALUE_PAIR *KeyValuePair;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ListHead = AllocatePool (sizeof (LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ListHead == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (ListHead);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (Len > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValuePair = AllocatePool (sizeof (ISCSI_KEY_VALUE_PAIR));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (KeyValuePair == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&KeyValuePair->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValuePair->Key = Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while ((Len > 0) && (*Data != '=')) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*Data == '=') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Data = '\0';
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len--;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (KeyValuePair);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValuePair->Value = Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (ListHead, &KeyValuePair->List);;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data += AsciiStrLen (KeyValuePair->Value) + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len -= (UINT32) AsciiStrLen (KeyValuePair->Value) + 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ListHead;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_ERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeKeyValueList (ListHead);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Get the value string by the key name from the key-value list. If found,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the key-value entry will be removed from the list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] KeyValueList The key-value list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Key The key name to find.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The value string.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL The key value pair cannot be found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCHAR8 *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiGetValueByKeyFromList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT LIST_ENTRY *KeyValueList,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CHAR8 *Key
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_KEY_VALUE_PAIR *KeyValuePair;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CHAR8 *Value;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, KeyValueList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValuePair = NET_LIST_USER_STRUCT (Entry, ISCSI_KEY_VALUE_PAIR, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (AsciiStrCmp (KeyValuePair->Key, Key) == 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Value = KeyValuePair->Value;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&KeyValuePair->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (KeyValuePair);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Value;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Free the key-value list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] KeyValueList The key-value list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiFreeKeyValueList (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN LIST_ENTRY *KeyValueList
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_KEY_VALUE_PAIR *KeyValuePair;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (KeyValueList)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Entry = NetListRemoveHead (KeyValueList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyValuePair = NET_LIST_USER_STRUCT (Entry, ISCSI_KEY_VALUE_PAIR, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (KeyValuePair);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (KeyValueList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Normalize the iSCSI name according to RFC.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Name The iSCSI name.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the iSCSI name.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The iSCSI name is valid and normalized.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR The iSCSI name is malformatted or not in the IQN format.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNormalizeName (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT CHAR8 *Name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN Len
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN Index;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (Index = 0; Index < Len; Index++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NET_IS_UPPER_CASE_CHAR (Name[Index])) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Convert the upper-case characters to lower-case ones.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Name[Index] = (CHAR8) (Name[Index] - 'A' + 'a');
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!NET_IS_LOWER_CASE_CHAR (Name[Index]) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync !NET_IS_DIGIT (Name[Index]) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Name[Index] != '-') &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Name[Index] != '.') &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (Name[Index] != ':')
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ASCII dash, dot, colon lower-case characters and digit characters
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // are allowed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Len < 4) || (CompareMem (Name, "iqn.", 4) != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Only IQN format is accepted now.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create an iSCSI task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Conn The connection on which the task control block will be created.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Tcb The newly created task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The task control block is created.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_NOT_READY The target cannot accept new commands.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNewTcb (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_CONNECTION *Conn,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT ISCSI_TCB **Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_TCB *NewTcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Tcb != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_SEQ_GT (Session->CmdSN, Session->MaxCmdSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_NOT_READY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewTcb = AllocateZeroPool (sizeof (ISCSI_TCB));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NewTcb == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&NewTcb->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewTcb->SoFarInOrder = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewTcb->InitiatorTaskTag = Session->InitiatorTaskTag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewTcb->CmdSN = Session->CmdSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NewTcb->Conn = Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (&Session->TcbList, &NewTcb->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Advance the initiator task tag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->InitiatorTaskTag++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->CmdSN++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Tcb = NewTcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Delete the tcb from the connection and destroy it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The tcb to delete.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiDelTcb (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RemoveEntryList (&Tcb->Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Find the task control block by the initator task tag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] TcbList The tcb list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] InitiatorTaskTag The initiator task tag.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The task control block found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL The task control block cannot be found.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncISCSI_TCB *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiFindTcbByITT (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN LIST_ENTRY *TcbList,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 InitiatorTaskTag
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_TCB *Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, TcbList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = NET_LIST_USER_STRUCT (Entry, ISCSI_TCB, Link);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb->InitiatorTaskTag == InitiatorTaskTag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a data segment, pad it, and calculate the CRC if needed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data to fill into the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataDigest Whether to calculate CRC for this data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The net buffer wrapping the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNewDataSegment (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN DataDigest
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_FRAGMENT Fragment[2];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 FragmentCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 PadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[0].Len = Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[0].Bulk = Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PadLen = ISCSI_GET_PAD_LEN (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PadLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[1].Len = PadLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Fragment[1].Bulk = (UINT8 *) &mDataSegPad;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FragmentCount = 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FragmentCount = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = NetbufFromExt (&Fragment[0], FragmentCount, 0, 0, IScsiNbufExtFree, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a iSCSI SCSI command PDU to encapsulate the command issued
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync by SCSI through the EXT SCSI PASS THRU Protocol.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Packet The EXT SCSI PASS THRU request packet containing the SCSI command.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The LUN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The tcb assocated with this SCSI command.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The created iSCSI SCSI command PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNewScsiCmdPdu (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *NbufList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *PduHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SCSI_COMMAND *ScsiCmd;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 AHSLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Length;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_ADDITIONAL_HEADER *Header;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_BI_EXP_READ_DATA_LEN_AHS *BiExpReadDataLenAHS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 ImmediateDataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AHSLength = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->DataDirection == DataBi) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Bidirectional Read/Write command, the bidirectional expected
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // read data length AHS is required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AHSLength += sizeof (ISCSI_BI_EXP_READ_DATA_LEN_AHS);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->CdbLength > 16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The CDB exceeds 16 bytes. An extended CDB AHS is required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AHSLength = (UINT8) (AHSLength + ISCSI_ROUNDUP (Packet->CdbLength - 16) + sizeof (ISCSI_ADDITIONAL_HEADER));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Length = sizeof (SCSI_COMMAND) + AHSLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduHeader = NetbufAlloc (Length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduHeader == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd = (SCSI_COMMAND *) NetbufAllocSpace (PduHeader, Length, NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ScsiCmd == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (PduHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Header = (ISCSI_ADDITIONAL_HEADER *) (ScsiCmd + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (ScsiCmd, Length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_OPCODE (ScsiCmd, ISCSI_OPCODE_SCSI_CMD, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (ScsiCmd, ISCSI_TASK_ATTR_SIMPLE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the READ/WRITE flags according to the IO type of this request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Packet->DataDirection) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DataIn:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->ExpDataXferLength = NTOHL (Packet->InTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DataOut:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_WRITE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case DataBi:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (ScsiCmd, SCSI_CMD_PDU_FLAG_READ | SCSI_CMD_PDU_FLAG_WRITE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->ExpDataXferLength = NTOHL (Packet->OutTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Fill the bidirectional expected read data length AHS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BiExpReadDataLenAHS = (ISCSI_BI_EXP_READ_DATA_LEN_AHS *) Header;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Header = (ISCSI_ADDITIONAL_HEADER *) (BiExpReadDataLenAHS + 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BiExpReadDataLenAHS->Length = NTOHS (5);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BiExpReadDataLenAHS->Type = ISCSI_AHS_TYPE_BI_EXP_READ_DATA_LEN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BiExpReadDataLenAHS->ExpReadDataLength = NTOHL (Packet->InTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->TotalAHSLength = AHSLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (ScsiCmd->Lun, &Lun, sizeof (ScsiCmd->Lun));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->InitiatorTaskTag = NTOHL (Tcb->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->CmdSN = NTOHL (Tcb->CmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiCmd->ExpStatSN = NTOHL (Tcb->Conn->ExpStatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (ScsiCmd->Cdb, Packet->Cdb, sizeof (ScsiCmd->Cdb));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->CdbLength > 16) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Header->Length = NTOHS ((UINT16) (Packet->CdbLength - 15));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Header->Type = ISCSI_AHS_TYPE_EXT_CDB;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Header + 1, (UINT8 *) Packet->Cdb + 16, Packet->CdbLength - 16);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = PduHeader;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Tcb->Conn->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImmediateDataLen = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->ImmediateData && (Packet->OutTransferLength != 0)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send immediate data in this SCSI Command PDU. The length of the immeidate
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // data is the minimum of FirstBurstLength, the data length to be xfered, and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the MaxRecvdataSegmentLength on this connection.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImmediateDataLen = MIN (Session->FirstBurstLength, Packet->OutTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ImmediateDataLen = MIN (ImmediateDataLen, Tcb->Conn->MaxRecvDataSegmentLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the data segment length in the PDU header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_DATASEG_LEN (ScsiCmd, ImmediateDataLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create the data segment.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = IScsiNewDataSegment ((UINT8 *) Packet->OutDataBuffer, ImmediateDataLen, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSeg == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (PduHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NbufList = AllocatePool (sizeof (LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NbufList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (PduHeader);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (DataSeg);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &PduHeader->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &DataSeg->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = NetbufFromBufList (NbufList, 0, 0, IScsiFreeNbufList, NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->InitialR2T ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (ImmediateDataLen == Session->FirstBurstLength) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (ImmediateDataLen == Packet->OutTransferLength)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unsolicited data out sequence is not allowed,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // or FirstBustLength data is already sent out by immediate data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // or all the OUT data accompany this SCSI packet are sent as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // immediate data. The final flag should be set on this SCSI Command
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (ScsiCmd, ISCSI_BHS_FLAG_FINAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Create a new iSCSI SCSI Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data to put into the Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Len Length of the data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] DataSN The DataSN of the Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block of this Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The LUN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The net buffer wrapping the Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncNET_BUF *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiNewDataOutPdu (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 DataSN,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *NbufList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *PduHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *DataSeg;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SCSI_DATA_OUT *DataOutHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_XFER_CONTEXT *XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NbufList = AllocatePool (sizeof (LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NbufList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate memory for the BHS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduHdr = NetbufAlloc (sizeof (ISCSI_SCSI_DATA_OUT));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Insert the BHS into the buffer list.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &PduHdr->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr = (ISCSI_SCSI_DATA_OUT *) NetbufAllocSpace (PduHdr, sizeof (ISCSI_SCSI_DATA_OUT), NET_BUF_TAIL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (DataOutHdr != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext = &Tcb->XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (DataOutHdr, sizeof (ISCSI_SCSI_DATA_OUT));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the flags and fields of the Data Out PDU BHS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_OPCODE (DataOutHdr, ISCSI_OPCODE_SCSI_DATA_OUT, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_DATASEG_LEN (DataOutHdr, Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr->InitiatorTaskTag = HTONL (Tcb->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr->TargetTransferTag = HTONL (XferContext->TargetTransferTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr->ExpStatSN = HTONL (Tcb->Conn->ExpStatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr->DataSN = HTONL (DataSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutHdr->BufferOffset = HTONL (XferContext->Offset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (XferContext->TargetTransferTag != ISCSI_RESERVED_TAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (&DataOutHdr->Lun, &Lun, sizeof (DataOutHdr->Lun));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build the data segment for this Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSeg = IScsiNewDataSegment (Data, Len, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSeg == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Put the data segment into the buffer list and combine it with the BHS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // into a full Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (NbufList, &DataSeg->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = NetbufFromBufList (NbufList, 0, 0, IScsiFreeNbufList, NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (NbufList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Generate a consecutive sequence of iSCSI SCSI Data Out PDUs.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data which will be carried by the sequence of iSCSI SCSI Data Out PDUs.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block of the data to send out.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The LUN the data will be sent to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return A list of net buffers with each of them wrapping an iSCSI SCSI Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval NULL Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncLIST_ENTRY *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiGenerateDataOutPduSequence (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *PduList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataSN;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *DataOutPdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION *Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_XFER_CONTEXT *XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *DataOutPacket;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduList = AllocatePool (sizeof (LIST_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (PduList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSN = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = Tcb->Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutPdu = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext = &Tcb->XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (XferContext->DesiredLength > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Determine the length of data this Data Out PDU can carry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataLen = MIN (XferContext->DesiredLength, Conn->MaxRecvDataSegmentLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Create a Data Out PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutPdu = IScsiNewDataOutPdu (Data, DataLen, DataSN, Tcb, Lun);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataOutPdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (PduList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduList = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InsertTailList (PduList, &DataOutPdu->List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the context and DataSN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data += DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->Offset += DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->DesiredLength -= DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSN++;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Set the F bit for the last data out PDU in this sequence.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutPacket = NetbufGetByte (DataOutPdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataOutPacket == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (PduList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduList = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SET_FLAG (DataOutPacket, ISCSI_BHS_FLAG_FINAL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return PduList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Send the Data in a sequence of Data Out PDUs one by one.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Data The data to carry by Data Out PDUs.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The LUN the data will be sent to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The data is sent out to the LUN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSendDataOutPduSequence (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *DataOutPduList;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync LIST_ENTRY *Entry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Generate the Data Out PDU sequence.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataOutPduList = IScsiGenerateDataOutPduSequence (Data, Tcb, Lun);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataOutPduList == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the Data Out PDU's one by one.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_LIST_FOR_EACH (Entry, DataOutPduList) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = NET_LIST_USER_STRUCT (Entry, NET_BUF, List);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoTransmit (&Tcb->Conn->TcpIo, Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiFreeNbufList (DataOutPduList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received iSCSI SCSI Data In PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Pdu The Data In PDU received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Packet The EXT SCSI PASS THRU request packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The check on the Data IN PDU is passed and some update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync actions are taken.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol errror occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_BAD_BUFFER_SIZEE The buffer was not the proper size for the request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiOnDataInRcvd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SCSI_DATA_IN *DataInHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataInHdr = (ISCSI_SCSI_DATA_IN *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataInHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataInHdr->InitiatorTaskTag = NTOHL (DataInHdr->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataInHdr->ExpCmdSN = NTOHL (DataInHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataInHdr->MaxCmdSN = NTOHL (DataInHdr->MaxCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataInHdr->DataSN = NTOHL (DataInHdr->DataSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the DataSN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Tcb->ExpDataSN, DataInHdr->DataSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataInHdr->InitiatorTaskTag != Tcb->InitiatorTaskTag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update the command related sequence numbers.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiUpdateCmdSN (Tcb->Conn->Session, DataInHdr->MaxCmdSN, DataInHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (DataInHdr, SCSI_DATA_IN_PDU_FLAG_STATUS_VALID)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!ISCSI_FLAG_ON (DataInHdr, ISCSI_BHS_FLAG_FINAL)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The S bit is on but the F bit is off.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->StatusXferd = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (DataInHdr, SCSI_DATA_IN_PDU_FLAG_OVERFLOW | SCSI_DATA_IN_PDU_FLAG_UNDERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Underflow and Overflow are mutual flags.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // S bit is on, the StatSN is valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Tcb->Conn->ExpStatSN, NTOHL (DataInHdr->StatSN));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->HostAdapterStatus = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->TargetStatus = DataInHdr->Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (DataInHdr, SCSI_RSP_PDU_FLAG_OVERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength += NTOHL (DataInHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_BAD_BUFFER_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (DataInHdr, SCSI_RSP_PDU_FLAG_UNDERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength -= NTOHL (DataInHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received iSCSI R2T PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Pdu The R2T PDU received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The Lun.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Packet The EXT SCSI PASS THRU request packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The R2T PDU is valid and the solicited data is sent out.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol errror occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiOnR2TRcvd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_READY_TO_TRANSFER *R2THdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_XFER_CONTEXT *XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr = (ISCSI_READY_TO_TRANSFER *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (R2THdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->InitiatorTaskTag = NTOHL (R2THdr->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->TargetTransferTag = NTOHL (R2THdr->TargetTransferTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->StatSN = NTOHL (R2THdr->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->R2TSeqNum = NTOHL (R2THdr->R2TSeqNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->BufferOffset = NTOHL (R2THdr->BufferOffset);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R2THdr->DesiredDataTransferLength = NTOHL (R2THdr->DesiredDataTransferLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((R2THdr->InitiatorTaskTag != Tcb->InitiatorTaskTag) || !ISCSI_SEQ_EQ (R2THdr->StatSN, Tcb->Conn->ExpStatSN)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check the sequence number.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Tcb->ExpDataSN, R2THdr->R2TSeqNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext = &Tcb->XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->TargetTransferTag = R2THdr->TargetTransferTag;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->Offset = R2THdr->BufferOffset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->DesiredLength = R2THdr->DesiredDataTransferLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (((XferContext->Offset + XferContext->DesiredLength) > Packet->OutTransferLength) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (XferContext->DesiredLength > Tcb->Conn->Session->MaxBurstLength)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send the data solicited by this R2T.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = (UINT8 *) Packet->OutDataBuffer + XferContext->Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiSendDataOutPduSequence (Data, Lun, Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received iSCSI SCSI Response PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Pdu The Response PDU received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Packet The EXT SCSI PASS THRU request packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The Response PDU is processed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol errror occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_BAD_BUFFER_SIZEE The buffer was not the proper size for the request.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiOnScsiRspRcvd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SCSI_RESPONSE *ScsiRspHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SENSE_DATA *SenseData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 DataSegLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiRspHdr = (SCSI_RESPONSE *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ScsiRspHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiRspHdr->InitiatorTaskTag = NTOHL (ScsiRspHdr->InitiatorTaskTag);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ScsiRspHdr->InitiatorTaskTag != Tcb->InitiatorTaskTag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiRspHdr->StatSN = NTOHL (ScsiRspHdr->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Tcb->Conn->ExpStatSN, ScsiRspHdr->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiRspHdr->MaxCmdSN = NTOHL (ScsiRspHdr->MaxCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ScsiRspHdr->ExpCmdSN = NTOHL (ScsiRspHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiUpdateCmdSN (Tcb->Conn->Session, ScsiRspHdr->MaxCmdSN, ScsiRspHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb->StatusXferd = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->HostAdapterStatus = ScsiRspHdr->Response;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->HostAdapterStatus != ISCSI_SERVICE_RSP_COMMAND_COMPLETE_AT_TARGET) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->TargetStatus = ScsiRspHdr->Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW | SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_OVERFLOW | SCSI_RSP_PDU_FLAG_UNDERFLOW)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_BI_READ_OVERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength += NTOHL (ScsiRspHdr->BiReadResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_BAD_BUFFER_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_BI_READ_UNDERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength -= NTOHL (ScsiRspHdr->BiReadResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_OVERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->DataDirection == DataIn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength += NTOHL (ScsiRspHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->OutTransferLength += NTOHL (ScsiRspHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_BAD_BUFFER_SIZE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (ISCSI_FLAG_ON (ScsiRspHdr, SCSI_RSP_PDU_FLAG_UNDERFLOW)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->DataDirection == DataIn) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->InTransferLength -= NTOHL (ScsiRspHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->OutTransferLength -= NTOHL (ScsiRspHdr->ResidualCount);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataSegLen = ISCSI_GET_DATASEG_LEN (ScsiRspHdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataSegLen != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SenseData = (ISCSI_SENSE_DATA *) NetbufGetByte (Pdu, sizeof (SCSI_RESPONSE), NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (SenseData == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SenseData->Length = NTOHS (SenseData->Length);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->SenseDataLength = (UINT8) MIN (SenseData->Length, Packet->SenseDataLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->SenseDataLength != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Packet->SenseData, &SenseData->Data[0], Packet->SenseDataLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->SenseDataLength = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Process the received NOP In PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Pdu The NOP In PDU received.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Tcb The task control block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The NOP In PDU is processed and the related sequence
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync numbers are updated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR Some kind of iSCSI protocol errror occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiOnNopInRcvd (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *Pdu,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_TCB *Tcb
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_NOP_IN *NopInHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NopInHdr = (ISCSI_NOP_IN *) NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NopInHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NopInHdr->StatSN = NTOHL (NopInHdr->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NopInHdr->ExpCmdSN = NTOHL (NopInHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NopInHdr->MaxCmdSN = NTOHL (NopInHdr->MaxCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NopInHdr->InitiatorTaskTag == ISCSI_RESERVED_TAG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NopInHdr->StatSN != Tcb->Conn->ExpStatSN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiCheckSN (&Tcb->Conn->ExpStatSN, NopInHdr->StatSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiUpdateCmdSN (Tcb->Conn->Session, NopInHdr->MaxCmdSN, NopInHdr->ExpCmdSN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Execute the SCSI command issued through the EXT SCSI PASS THRU protocol.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PassThru The EXT SCSI PASS THRU protocol.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Target The target ID.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Lun The LUN.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Packet The request packet containing IO request, SCSI command
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync buffer and buffers to read/write.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCES The SCSI command is executed and the result is updated to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the Packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_DEVICE_ERROR Session state was not as required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_PROTOCOL_ERROR There is no such data in the net buffer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Other errors as indicated.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiExecuteScsiCommand (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *PassThru,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT8 *Target,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT64 Lun,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_DRIVER_DATA *Private;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_SESSION *Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_EVENT TimeoutEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION *Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_TCB *Tcb;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *Pdu;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_XFER_CONTEXT *XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_IN_BUFFER_CONTEXT InBufferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 Timeout;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *PduHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Private = ISCSI_DRIVER_DATA_FROM_EXT_SCSI_PASS_THRU (PassThru);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session = Private->Session;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Tcb = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimeoutEvent = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Timeout = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->State != SESSION_STATE_LOGGED_IN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = NET_LIST_USER_STRUCT_S (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Conns.ForwardLink,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Link,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION_SIGNATURE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet->Timeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Timeout = MultU64x32 (Packet->Timeout, 4);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiNewTcb (Conn, &Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Encapsulate the SCSI request packet into an iSCSI SCSI Command PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Pdu = IScsiNewScsiCmdPdu (Packet, Lun, Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Pdu == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext = &Tcb->XferContext;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduHdr = NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->Offset = ISCSI_GET_DATASEG_LEN (PduHdr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Transmit the SCSI Command PDU.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TcpIoTransmit (&Conn->TcpIo, Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Session->InitialR2T &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (XferContext->Offset < Session->FirstBurstLength) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (XferContext->Offset < Packet->OutTransferLength)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Unsolicited Data-Out sequence is allowed. There is remaining SCSI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // OUT data, and the limit of FirstBurstLength is not reached.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->TargetTransferTag = ISCSI_RESERVED_TAG;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync XferContext->DesiredLength = MIN (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->FirstBurstLength,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->OutTransferLength - XferContext->Offset
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Data = (UINT8 *) Packet->OutDataBuffer + XferContext->Offset;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiSendDataOutPduSequence (Data, Lun, Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InBufferContext.InData = (UINT8 *) Packet->InDataBuffer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InBufferContext.InDataLen = Packet->InTransferLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!Tcb->StatusXferd) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Start the timeout timer.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Timeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = gBS->SetTimer (Conn->TimeoutEvent, TimerRelative, Timeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TimeoutEvent = Conn->TimeoutEvent;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Try to receive PDU from target.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiReceivePdu (Conn, &Pdu, &InBufferContext, FALSE, FALSE, TimeoutEvent);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PduHdr = NetbufGetByte (Pdu, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PduHdr == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (ISCSI_GET_OPCODE (PduHdr)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_SCSI_DATA_IN:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiOnDataInRcvd (Pdu, Tcb, Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_R2T:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiOnR2TRcvd (Pdu, Tcb, Lun, Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_SCSI_RSP:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiOnScsiRspRcvd (Pdu, Tcb, Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_NOP_IN:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiOnNopInRcvd (Pdu, Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T0:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T1:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case ISCSI_OPCODE_VENDOR_T2:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // These messages are vendor specific. Skip them.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_PROTOCOL_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (Pdu);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (TimeoutEvent != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->SetTimer (TimeoutEvent, TimerCancel, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Tcb != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiDelTcb (Tcb);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Reinstate the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (IScsiSessionReinstatement (Session))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_DEVICE_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Reinstate the session on some error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Session The iSCSI session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The session is reinstated from some error.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Other Reinstatement failed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSessionReinstatement (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN ISCSI_SESSION *Session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Session->State == SESSION_STATE_LOGGED_IN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Abort the session and re-init it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiSessionAbort (Session);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiSessionInit (Session, TRUE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Login again.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IScsiSessionLogin (Session);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Initialize some session parameters before login.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Recovery Whether the request is from a fresh new start or recovery.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSessionInit (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_SESSION *Session,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN BOOLEAN Recovery
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Recovery) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Signature = ISCSI_SESSION_SIGNATURE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->State = SESSION_STATE_FREE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Session->Conns);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync InitializeListHead (&Session->TcbList);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Tsih = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->CmdSN = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->InitiatorTaskTag = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->NextCid = 1;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->TargetPortalGroupTag = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxConnections = ISCSI_MAX_CONNS_PER_SESSION;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->InitialR2T = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ImmediateData = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxBurstLength = 262144;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->FirstBurstLength = MAX_RECV_DATA_SEG_LEN_IN_FFP;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Wait = 2;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DefaultTime2Retain = 20;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->MaxOutstandingR2T = DEFAULT_MAX_OUTSTANDING_R2T;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DataPDUInOrder = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->DataSequenceInOrder = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->ErrorRecoveryLevel = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Abort the iSCSI session. That is, reset all the connection(s), and free the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in, out] Session The iSCSI session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncIScsiSessionAbort (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT ISCSI_SESSION *Session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION *Conn;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_GUID *ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Session->State != SESSION_STATE_LOGGED_IN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (!IsListEmpty (&Session->Conns));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (!IsListEmpty (&Session->Conns)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn = NET_LIST_USER_STRUCT_S (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Conns.ForwardLink,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Link,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ISCSI_CONNECTION_SIGNATURE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!Conn->Ipv6Flag) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid = &gEfiTcp4ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid = &gEfiTcp6ProtocolGuid;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gBS->CloseProtocol (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Conn->TcpIo.Handle,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ProtocolGuid,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Private->Image,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->Private->ExtScsiPassThruHandle
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiConnReset (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiDetatchConnection (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IScsiDestroyConnection (Conn);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Session->State = SESSION_STATE_FAILED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return ;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}