mtftp4impl.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 930 行 · 第 1/2 页

C
930
字号

  Instance  - The MTFTP instance
  Override  - The override data to validate.

Returns:

  TRUE if the override data is valid, otherwise FALSE.

--*/
{
  EFI_MTFTP4_CONFIG_DATA    *Config;
  IP4_ADDR                  Ip;
  IP4_ADDR                  Netmask;
  IP4_ADDR                  Gateway;

  if (!Ip4IsUnicast (EFI_NTOHL (Override->ServerIp), 0)) {
    return FALSE;
  }

  Config  = &Instance->Config;
  Gateway = EFI_NTOHL (Override->GatewayIp);

  if (!Config->UseDefaultSetting && (Gateway != 0)) {
    Netmask = EFI_NTOHL (Config->SubnetMask);
    Ip   = EFI_NTOHL (Config->StationIp);

    if (!Ip4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {
      return FALSE;
    }
  }

  return TRUE;
}

BOOLEAN
Mtftp4GetMapping (
  IN MTFTP4_PROTOCOL        *Instance,
  IN UDP_IO_PORT            *UdpPort,
  IN EFI_UDP4_CONFIG_DATA   *UdpCfgData
  )
/*++

Routine Description:

  Poll the UDP to get the IP4 default address, which may be retrieved 
  by DHCP. The default time out value is 5 seconds. If IP has retrieved
  the default address, the UDP is reconfigured.

Arguments:

  Instance    - The Mtftp instance
  UdpPort     - The UDP port to poll
  UdpCfgData  - The UDP configure data to reconfigure the UDP port.

Returns:

  TRUE if the default address is retrieved and UDP is reconfigured. 
  Otherwise FALSE.

--*/
{
  MTFTP4_SERVICE            *Service;
  EFI_IP4_MODE_DATA         Ip4Mode;
  EFI_UDP4_PROTOCOL         *Udp;

  ASSERT (Instance->Config.UseDefaultSetting);

  Service = Instance->Service;
  Udp     = UdpPort->Udp;

  if (Service->TimeToGetMap == 0) {
    Service->TimeToGetMap = MTFTP4_TIME_TO_GETMAP;
  }

  while (Service->TimeToGetMap != 0) {
    Udp->Poll (Udp);

    if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) && 
        Ip4Mode.IsConfigured) {

      Udp->Configure (Udp, NULL);
      return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
    }
  }

  return FALSE;
}

STATIC
EFI_STATUS
Mtftp4ConfigUnicastPort (
  IN UDP_IO_PORT            *UdpIo,
  IN MTFTP4_PROTOCOL        *Instance
  )
/*++

Routine Description:

  Configure the UDP port for unicast receiving.

Arguments:

  UdpIo     - The UDP port
  Instance  - The MTFTP session

Returns:

  EFI_SUCCESS - The UDP port is successfully configured for the session
  to unicast receive.

--*/
{
  EFI_MTFTP4_CONFIG_DATA    *Config;
  EFI_UDP4_CONFIG_DATA      UdpConfig;
  EFI_STATUS                Status;

  Config = &Instance->Config;

  UdpConfig.AcceptBroadcast     = FALSE;
  UdpConfig.AcceptPromiscuous   = FALSE;
  UdpConfig.AcceptAnyPort       = FALSE;
  UdpConfig.AllowDuplicatePort  = FALSE;
  UdpConfig.TypeOfService       = 0;
  UdpConfig.TimeToLive          = 64;
  UdpConfig.DoNotFragment       = FALSE;
  UdpConfig.ReceiveTimeout      = 0;
  UdpConfig.TransmitTimeout     = 0;
  UdpConfig.UseDefaultAddress   = Config->UseDefaultSetting;
  UdpConfig.StationAddress      = Config->StationIp;
  UdpConfig.SubnetMask          = Config->SubnetMask;
  UdpConfig.StationPort         = 0;
  UdpConfig.RemotePort          = 0;
  EFI_IP4 (UdpConfig.RemoteAddress) = HTONL (Instance->ServerIp);

  Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfig);

  if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {
    return EFI_SUCCESS;
  }

  return Status;
}

STATIC
EFI_STATUS
Mtftp4Start (
  IN EFI_MTFTP4_PROTOCOL    *This,
  IN EFI_MTFTP4_TOKEN       *Token,
  IN UINT16                 Operation
  )
/*++

Routine Description:

  Start the MTFTP session to do the operation, such as read file,
  write file, and read directory.

Arguments:

  This      - The MTFTP session
  Token     - The token than encapsues the user's request.
  Operation - The operation to do

Returns:

  EFI_INVALID_PARAMETER - Some of the parameters are invalid.
  EFI_NOT_STARTED       - The MTFTP session hasn't been configured.
  EFI_ALREADY_STARTED   - There is pending operation for the session.
  EFI_SUCCESS           - The operation is successfully started.

--*/
{
  MTFTP4_PROTOCOL           *Instance;
  EFI_MTFTP4_OVERRIDE_DATA  *Override;
  EFI_MTFTP4_CONFIG_DATA    *Config;
  EFI_TPL                   OldTpl;
  EFI_STATUS                Status;

  //
  // Validate the parameters
  //
  if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||
      ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // User must provide at least one method to collect the data for download.
  //
  if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&
      ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {
    return EFI_INVALID_PARAMETER;
  }

  //
  // User must provide at least one method to provide the data for upload.
  //
  if ((Operation == EFI_MTFTP4_OPCODE_WRQ) && 
     ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = MTFTP4_PROTOCOL_FROM_THIS (This);

  if (Instance->State != MTFTP4_STATE_CONFIGED) {
    return EFI_NOT_STARTED;
  }

  if (Instance->Operation != 0) {
    return EFI_ACCESS_DENIED;
  }
  
  //
  // Set the Operation now to prevent the application start other
  // operations. Don't get the lock or raise TPL here because
  // Mtftp4GetMapping, which is called by UdpIoCreatePort, must be
  // run below the NET_TPL_CALLBACK
  //
  Instance->Operation = Operation;
  Override            = Token->OverrideData;

  if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {
    Status = EFI_INVALID_PARAMETER;
    goto ON_ERROR;
  }

  if (Token->OptionCount != 0) {
    Status = Mtftp4ParseOption (
               Token->OptionList,
               Token->OptionCount,
               TRUE,
               &Instance->RequestOption
               );

    if (EFI_ERROR (Status)) {
      goto ON_ERROR;
    }
  }
  
  //
  // Set the operation parameters from the configuration or override data.
  //
  Config                  = &Instance->Config;
  Instance->Token         = Token;
  Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;
  Instance->ServerIp      = EFI_NTOHL (Config->ServerIp);
  Instance->ListeningPort = Config->InitialServerPort;
  Instance->ConnectedPort = 0;
  Instance->Gateway       = EFI_NTOHL (Config->GatewayIp);
  Instance->MaxRetry      = Config->TryCount;
  Instance->Timeout       = Config->TimeoutValue;
  Instance->Master        = TRUE;

  if (Override != NULL) {
    Instance->Gateway       = EFI_NTOHL (Override->GatewayIp);
    Instance->ServerIp      = EFI_NTOHL (Override->ServerIp);
    Instance->ListeningPort = Override->ServerPort;
    Instance->MaxRetry      = Override->TryCount;
    Instance->Timeout       = Override->TimeoutValue;
  }

  if (Instance->ListeningPort == 0) {
    Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;
  }

  if (Instance->MaxRetry == 0) {
    Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;
  }

  if (Instance->Timeout == 0) {
    Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;
  }
  
  //
  // Config the unicast UDP child to send initial request
  //
  Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  //
  // Build and send an initial requests
  //
  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);

  if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
    Status = Mtftp4WrqStart (Instance, Operation);
  } else {
    Status = Mtftp4RrqStart (Instance, Operation);
  }

  NET_RESTORE_TPL (OldTpl);

  if (EFI_ERROR (Status)) {
    goto ON_ERROR;
  }
  
  //
  // Return immediately for asynchronous operation or poll the
  // instance for synchronous operation.
  //
  Token->Status = EFI_NOT_READY;
  
  if (Token->Event != NULL) {
    return EFI_SUCCESS;
  }

  while (Token->Status == EFI_NOT_READY) {
    This->Poll (This);
  }

  return Token->Status;

ON_ERROR:
  Mtftp4CleanOperation (Instance, Status);
  return Status;
}

STATIC
EFI_STATUS
EFIAPI
EfiMtftp4ReadFile (
  IN EFI_MTFTP4_PROTOCOL    *This,
  IN EFI_MTFTP4_TOKEN       *Token
  )
/*++

Routine Description:

  Read a file from the server.

Arguments:

  This  - The Mtftp protocol instance.
  Token - The user's request wrap token.

Returns:

  EFI_SUCCESS - The ReadFile has finished, the file has been downloaded
                if it is synchronous operation, otherwise it has been 
                initated.
  Others      - Some error happened.                

--*/
{
  return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);
}

STATIC
EFI_STATUS
EFIAPI
EfiMtftp4WriteFile (
  IN EFI_MTFTP4_PROTOCOL    *This,
  IN EFI_MTFTP4_TOKEN       *Token
  )
/*++

Routine Description:

  Upload a file to the server.

Arguments:

  This  - The MTFTP protocol session
  Token - The user's request wrap token.

Returns:

  EFI_SUCCESS - The WriteFile has finished, the file has been uploaded
                if it is synchronous operation, otherwise it has been 
                initated.
  Others      - Some error happened.                

--*/
{
  return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);
}

STATIC
EFI_STATUS
EFIAPI
EfiMtftp4ReadDirectory (
  IN EFI_MTFTP4_PROTOCOL        *This,
  IN EFI_MTFTP4_TOKEN           *Token
  )
/*++

Routine Description:

  Read a directory from the server. The only difference
  between ReadFile and ReadDirectory is the opcode used.

Arguments:

  This  - The MTFTP protocol session
  Token - The user's request wrap token.

Returns:

  EFI_SUCCESS - The ReadDirectory has finished, the directory has been 
                downloaded as a file if it is synchronous operation, 
                otherwise it has been initated.
  Others      - Some error happened.                

--*/
{
  return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);
}

STATIC
EFI_STATUS
EFIAPI
EfiMtftp4Poll (
  IN EFI_MTFTP4_PROTOCOL    *This
  )
/*++

Routine Description:

  Poll the network stack to accelerate the packet process.

Arguments:

  This  - The MTFTP protocol instance.

Returns:

  EFI_INVALID_PARAMETER - This is NULL.
  EFI_NOT_STARTED       - The MTFTP session hasn't been configured.
  EFI_DEVICE_ERROR      - The MTFTP session has been destoried.

--*/
{
  MTFTP4_PROTOCOL           *Instance;
  EFI_UDP4_PROTOCOL         *Udp;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = MTFTP4_PROTOCOL_FROM_THIS (This);

  if (Instance->State == MTFTP4_STATE_UNCONFIGED) {
    return EFI_NOT_STARTED;
  } else if (Instance->State == MTFTP4_STATE_DESTORY) {
    return EFI_DEVICE_ERROR;
  }

  Udp = Instance->UnicastPort->Udp;
  return Udp->Poll (Udp);
}

EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {
  EfiMtftp4GetModeData,
  EfiMtftp4Configure,
  EfiMtftp4GetInfo,
  EfiMtftp4ParseOptions,
  EfiMtftp4ReadFile,
  EfiMtftp4WriteFile,
  EfiMtftp4ReadDirectory,
  EfiMtftp4Poll
};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?